summaryrefslogtreecommitdiffstats
path: root/gdbmobj/gdbmobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdbmobj/gdbmobj.c')
-rw-r--r--gdbmobj/gdbmobj.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/gdbmobj/gdbmobj.c b/gdbmobj/gdbmobj.c
new file mode 100644
index 0000000..61f6f93
--- /dev/null
+++ b/gdbmobj/gdbmobj.c
@@ -0,0 +1,177 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc. See COPYING for
+** distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gdbmobj.h"
+#include <stdlib.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+void gdbmobj_init(struct gdbmobj *obj)
+{
+ obj->has_dbf=0;
+ obj->prev_key=0;
+ obj->prev_key_len=0;
+}
+
+void gdbmobj_close(struct gdbmobj *obj)
+{
+ if (obj->has_dbf)
+ {
+ obj->has_dbf=0;
+ gdbm_close(obj->dbf);
+ }
+ if (obj->prev_key)
+ {
+ free(obj->prev_key);
+ obj->prev_key=0;
+ }
+}
+
+int gdbmobj_open(struct gdbmobj *obj, const char *filename, const char *modestr)
+{
+int mode=GDBM_READER;
+
+ for ( ; *modestr; modestr++)
+ switch (*modestr) {
+ case 'c':
+ case 'C':
+ mode=GDBM_WRCREAT;
+ break;
+ case 'w':
+ case 'W':
+ mode=GDBM_WRITER;
+ break;
+ case 'n':
+ case 'N':
+ mode=GDBM_NEWDB;
+ break;
+ }
+
+ gdbmobj_close(obj);
+ if ((obj->dbf=gdbm_open((char *)filename, 0, mode, 0664, 0)) != 0)
+ {
+ /* Where possible, set the close-on-exec bit */
+
+#if HAVE_GDBM_FDESC
+#ifdef FD_CLOEXEC
+
+ int fd=gdbm_fdesc(obj->dbf);
+
+ if (fd >= 0) fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+#endif
+
+ obj->has_dbf=1;
+ return (0);
+ }
+ return (-1);
+}
+
+int gdbmobj_store(struct gdbmobj *obj, const char *key, size_t keylen,
+ const char *data,
+ size_t datalen,
+ const char *mode)
+{
+datum dkey;
+datum dval;
+
+ dkey.dptr=(char *)key;
+ dkey.dsize=keylen;
+
+ dval.dptr=(char *)data;
+ dval.dsize=datalen;
+
+ return (obj->has_dbf ? gdbm_store(obj->dbf, dkey, dval, (
+ *mode == 'i' || *mode == 'I' ?
+ GDBM_INSERT:GDBM_REPLACE)):-1);
+}
+
+int gdbmobj_exists(struct gdbmobj *obj, const char *key, size_t keylen)
+{
+datum dkey;
+
+ if (!obj->has_dbf) return (0);
+
+ dkey.dptr=(char *)key;
+ dkey.dsize=keylen;
+
+ if (gdbm_exists(obj->dbf, dkey)) return (1);
+ return (0);
+}
+
+char *gdbm_dofetch(struct gdbmobj *, const char *, size_t, size_t *);
+
+char *gdbmobj_fetch(struct gdbmobj *obj, const char *key, size_t keylen,
+ size_t *datalen, const char *options)
+{
+char *p;
+
+ for (;;)
+ {
+ if ((p=gdbm_dofetch(obj, key, keylen, datalen)) != 0)
+ return (p);
+ if (!options) break;
+ if (*options == 'I')
+ {
+ while (keylen && key[--keylen] != '.')
+ ;
+ if (!keylen) break;
+ continue;
+ }
+ if (*options == 'D')
+ {
+ size_t i;
+
+ for (i=0; i<keylen; i++)
+ if (key[i] == '@') { ++i; break; }
+ if (i < keylen)
+ {
+ if ((p=gdbm_dofetch(obj, key, i, datalen)) != 0)
+ return (p);
+ key += i;
+ keylen -= i;
+ continue;
+ }
+
+ for (i=0; i<keylen; i++)
+ if (key[i] == '.') { ++i; break; }
+ if (i < keylen)
+ {
+ key += i;
+ keylen -= i;
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ return (0);
+}
+
+char *gdbm_dofetch(struct gdbmobj *obj,
+ const char *key, size_t keylen, size_t *datalen)
+{
+datum dkey, val;
+
+ if (!obj->has_dbf) return (0);
+
+ dkey.dptr=(char *)key;
+ dkey.dsize=keylen;
+
+ val=gdbm_fetch(obj->dbf, dkey);
+
+ if (!val.dptr) return (0);
+ *datalen=val.dsize;
+ return (val.dptr);
+}