summaryrefslogtreecommitdiff
path: root/src/myndbm.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2005-10-03 13:43:40 +0000
committer <>2014-09-25 11:25:48 +0000
commit10de491ef0bc43827ab8631a4c02860134e620a9 (patch)
tree22e734337cc9aa5d9b1d7c71261d160b6a60634d /src/myndbm.c
downloadcvs-tarball-10de491ef0bc43827ab8631a4c02860134e620a9.tar.gz
Imported from /home/lorry/working-area/delta_cvs-tarball/cvs-1.12.13.tar.bz2.HEADcvs-1.12.13master
Diffstat (limited to 'src/myndbm.c')
-rw-r--r--src/myndbm.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/myndbm.c b/src/myndbm.c
new file mode 100644
index 0000000..d7ef885
--- /dev/null
+++ b/src/myndbm.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
+ * and others.
+ *
+ * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
+ * Portions Copyright (C) 1989-1992, Brian Berliner
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS source distribution.
+ *
+ * A simple ndbm-emulator for CVS. It parses a text file of the format:
+ *
+ * key value
+ *
+ * at dbm_open time, and loads the entire file into memory. As such, it is
+ * probably only good for fairly small modules files. Ours is about 30K in
+ * size, and this code works fine.
+ */
+
+#include "cvs.h"
+
+#include "getdelim.h"
+#include "getline.h"
+
+#ifdef MY_NDBM
+# ifndef O_ACCMODE
+# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+# endif /* defined O_ACCMODE */
+
+static void mydbm_load_file (FILE *, List *, char *);
+
+/* Returns NULL on error in which case errno has been set to indicate
+ the error. Can also call error() itself. */
+/* ARGSUSED */
+DBM *
+mydbm_open (char *file, int flags, int mode)
+{
+ FILE *fp;
+ DBM *db;
+
+ fp = CVS_FOPEN (file, (flags & O_ACCMODE) != O_RDONLY
+ ? FOPEN_BINARY_READWRITE : FOPEN_BINARY_READ);
+ if (fp == NULL && !(existence_error (errno) && (flags & O_CREAT)))
+ return NULL;
+
+ db = xmalloc (sizeof (*db));
+ db->dbm_list = getlist ();
+ db->modified = 0;
+ db->name = xstrdup (file);
+
+ if (fp != NULL)
+ {
+ mydbm_load_file (fp, db->dbm_list, file);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s",
+ primary_root_inverse_translate (file));
+ }
+ return db;
+}
+
+
+
+static int
+write_item (Node *node, void *data)
+{
+ FILE *fp = data;
+ fputs (node->key, fp);
+ fputs (" ", fp);
+ fputs (node->data, fp);
+ fputs ("\012", fp);
+ return 0;
+}
+
+
+
+void
+mydbm_close (DBM *db)
+{
+ if (db->modified)
+ {
+ FILE *fp;
+ fp = CVS_FOPEN (db->name, FOPEN_BINARY_WRITE);
+ if (fp == NULL)
+ error (1, errno, "cannot write %s", db->name);
+ walklist (db->dbm_list, write_item, fp);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", db->name);
+ }
+ free (db->name);
+ dellist (&db->dbm_list);
+ free (db);
+}
+
+
+
+datum
+mydbm_fetch (DBM *db, datum key)
+{
+ Node *p;
+ char *s;
+ datum val;
+
+ /* make sure it's null-terminated */
+ s = xmalloc (key.dsize + 1);
+ (void) strncpy (s, key.dptr, key.dsize);
+ s[key.dsize] = '\0';
+
+ p = findnode (db->dbm_list, s);
+ if (p)
+ {
+ val.dptr = p->data;
+ val.dsize = strlen (p->data);
+ }
+ else
+ {
+ val.dptr = NULL;
+ val.dsize = 0;
+ }
+ free (s);
+ return val;
+}
+
+
+
+datum
+mydbm_firstkey (DBM *db)
+{
+ Node *head, *p;
+ datum key;
+
+ head = db->dbm_list->list;
+ p = head->next;
+ if (p != head)
+ {
+ key.dptr = p->key;
+ key.dsize = strlen (p->key);
+ }
+ else
+ {
+ key.dptr = NULL;
+ key.dsize = 0;
+ }
+ db->dbm_next = p->next;
+ return key;
+}
+
+
+
+datum
+mydbm_nextkey (DBM *db)
+{
+ Node *head, *p;
+ datum key;
+
+ head = db->dbm_list->list;
+ p = db->dbm_next;
+ if (p != head)
+ {
+ key.dptr = p->key;
+ key.dsize = strlen (p->key);
+ }
+ else
+ {
+ key.dptr = NULL;
+ key.dsize = 0;
+ }
+ db->dbm_next = p->next;
+ return key;
+}
+
+
+
+/* Note: only updates the in-memory copy, which is written out at
+ mydbm_close time. Note: Also differs from DBM in that on duplication,
+ it gives a warning, rather than either DBM_INSERT or DBM_REPLACE
+ behavior. */
+int
+mydbm_store (DBM *db, datum key, datum value, int flags)
+{
+ Node *node;
+
+ node = getnode ();
+ node->type = NDBMNODE;
+
+ node->key = xmalloc (key.dsize + 1);
+ *node->key = '\0';
+ strncat (node->key, key.dptr, key.dsize);
+
+ node->data = xmalloc (value.dsize + 1);
+ *(char *)node->data = '\0';
+ strncat (node->data, value.dptr, value.dsize);
+
+ db->modified = 1;
+ if (addnode (db->dbm_list, node) == -1)
+ {
+ error (0, 0, "attempt to insert duplicate key `%s'", node->key);
+ freenode (node);
+ return 0;
+ }
+ return 0;
+}
+
+
+
+/* Load a DBM file.
+ *
+ * INPUTS
+ * filename Used in error messages.
+ */
+static void
+mydbm_load_file (FILE *fp, List *list, char *filename)
+{
+ char *line = NULL;
+ size_t line_size;
+ char *value;
+ size_t value_allocated;
+ char *cp, *vp;
+ int cont;
+ int line_length;
+ int line_num;
+
+ value_allocated = 1;
+ value = xmalloc (value_allocated);
+
+ cont = 0;
+ line_num=0;
+ while ((line_length = getdelim (&line, &line_size, '\012', fp)) >= 0)
+ {
+ line_num++;
+ if (line_length > 0 && line[line_length - 1] == '\012')
+ {
+ /* Strip the newline. */
+ --line_length;
+ line[line_length] = '\0';
+ }
+ if (line_length > 0 && line[line_length - 1] == '\015')
+ {
+ /* If the file (e.g. modules) was written on an NT box, it will
+ contain CRLF at the ends of lines. Strip them (we can't do
+ this by opening the file in text mode because we might be
+ running on unix). */
+ --line_length;
+ line[line_length] = '\0';
+ }
+
+ /*
+ * Add the line to the value, at the end if this is a continuation
+ * line; otherwise at the beginning, but only after any trailing
+ * backslash is removed.
+ */
+ if (!cont)
+ value[0] = '\0';
+
+ /*
+ * See if the line we read is a continuation line, and strip the
+ * backslash if so.
+ */
+ if (line_length > 0)
+ cp = &line[line_length - 1];
+ else
+ cp = line;
+ if (*cp == '\\')
+ {
+ cont = 1;
+ *cp = '\0';
+ --line_length;
+ }
+ else
+ {
+ cont = 0;
+ }
+ expand_string (&value,
+ &value_allocated,
+ strlen (value) + line_length + 5);
+ strcat (value, line);
+
+ if (value[0] == '#')
+ continue; /* comment line */
+ vp = value;
+ while (*vp && isspace ((unsigned char) *vp))
+ vp++;
+ if (*vp == '\0')
+ continue; /* empty line */
+
+ /*
+ * If this was not a continuation line, add the entry to the database
+ */
+ if (!cont)
+ {
+ Node *p = getnode ();
+ char *kp;
+
+ kp = vp;
+ while (*vp && !isspace ((unsigned char) *vp))
+ vp++;
+ if (*vp)
+ *vp++ = '\0'; /* NULL terminate the key */
+ p->type = NDBMNODE;
+ p->key = xstrdup (kp);
+ while (*vp && isspace ((unsigned char) *vp))
+ vp++; /* skip whitespace to value */
+ if (*vp == '\0')
+ {
+ if (!really_quiet)
+ error (0, 0,
+ "warning: NULL value for key `%s' at line %d of `%s'",
+ p->key, line_num,
+ primary_root_inverse_translate (filename));
+ freenode (p);
+ continue;
+ }
+ p->data = xstrdup (vp);
+ if (addnode (list, p) == -1)
+ {
+ if (!really_quiet)
+ error (0, 0,
+ "duplicate key found for `%s' at line %d of `%s'",
+ p->key, line_num,
+ primary_root_inverse_translate (filename));
+ freenode (p);
+ }
+ }
+ }
+ if (line_length < 0 && !feof (fp))
+ error (0, errno, "cannot read file `%s' in mydbm_load_file",
+ primary_root_inverse_translate (filename));
+
+ free (line);
+ free (value);
+}
+
+#endif /* MY_NDBM */