#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
static void mydbm_load_file (FILE *, List *, char *);
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;
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;
}
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;
}
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')
{
--line_length;
line[line_length] = '\0';
}
if (line_length > 0 && line[line_length - 1] == '\015')
{
--line_length;
line[line_length] = '\0';
}
if (!cont)
value[0] = '\0';
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;
vp = value;
while (*vp && isspace ((unsigned char) *vp))
vp++;
if (*vp == '\0')
continue;
if (!cont)
{
Node *p = getnode ();
char *kp;
kp = vp;
while (*vp && !isspace ((unsigned char) *vp))
vp++;
if (*vp)
*vp++ = '\0';
p->type = NDBMNODE;
p->key = xstrdup (kp);
while (*vp && isspace ((unsigned char) *vp))
vp++;
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