summaryrefslogtreecommitdiff
path: root/libdb
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2019-08-03 12:15:34 +0100
committerColin Watson <cjwatson@debian.org>2019-08-03 12:15:34 +0100
commitf22ec2853f6ea2123dc4a1fee566a828e8d86bc6 (patch)
treeb4d8e7309d6d25acee9b3a94f6e07acb209daacd /libdb
parent182141146d0ad9c735949840504bdfc66332da4e (diff)
parent74d8f72dc1ca9620d3e8e1ae2ed9b19047ba348f (diff)
Import man-db_2.8.6.orig.tar.xz
Diffstat (limited to 'libdb')
-rw-r--r--libdb/Makefile.in5
-rw-r--r--libdb/db_btree.c33
-rw-r--r--libdb/db_delete.c58
-rw-r--r--libdb/db_gdbm.c176
-rw-r--r--libdb/db_lookup.c195
-rw-r--r--libdb/db_ndbm.c8
-rw-r--r--libdb/db_storage.h24
-rw-r--r--libdb/mydbm.h5
8 files changed, 249 insertions, 255 deletions
diff --git a/libdb/Makefile.in b/libdb/Makefile.in
index 6a43a773..afc0b5ea 100644
--- a/libdb/Makefile.in
+++ b/libdb/Makefile.in
@@ -99,6 +99,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \
$(top_srcdir)/m4/man-arg-db.m4 \
$(top_srcdir)/m4/man-arg-device.m4 \
$(top_srcdir)/m4/man-arg-mandirs.m4 \
+ $(top_srcdir)/m4/man-arg-manual.m4 \
$(top_srcdir)/m4/man-arg-override-dir.m4 \
$(top_srcdir)/m4/man-arg-sections.m4 \
$(top_srcdir)/m4/man-arg-setuid.m4 \
@@ -121,7 +122,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \
$(top_srcdir)/gl/m4/btowc.m4 \
$(top_srcdir)/gl/m4/builtin-expect.m4 \
$(top_srcdir)/gl/m4/canonicalize.m4 \
- $(top_srcdir)/gl/m4/chdir-long.m4 \
+ $(top_srcdir)/gl/m4/chdir-long.m4 $(top_srcdir)/gl/m4/chown.m4 \
$(top_srcdir)/gl/m4/clock_time.m4 $(top_srcdir)/gl/m4/close.m4 \
$(top_srcdir)/gl/m4/closedir.m4 $(top_srcdir)/gl/m4/codeset.m4 \
$(top_srcdir)/gl/m4/d-ino.m4 $(top_srcdir)/gl/m4/d-type.m4 \
@@ -165,7 +166,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \
$(top_srcdir)/gl/m4/intmax_t.m4 \
$(top_srcdir)/gl/m4/inttypes_h.m4 $(top_srcdir)/gl/m4/ioctl.m4 \
$(top_srcdir)/gl/m4/langinfo_h.m4 \
- $(top_srcdir)/gl/m4/largefile.m4 \
+ $(top_srcdir)/gl/m4/largefile.m4 $(top_srcdir)/gl/m4/lchown.m4 \
$(top_srcdir)/gl/m4/lib-ignore.m4 \
$(top_srcdir)/gl/m4/lib-ld.m4 $(top_srcdir)/gl/m4/lib-link.m4 \
$(top_srcdir)/gl/m4/lib-prefix.m4 \
diff --git a/libdb/db_btree.c b/libdb/db_btree.c
index 4469bf61..b4e426cc 100644
--- a/libdb/db_btree.c
+++ b/libdb/db_btree.c
@@ -32,29 +32,27 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <sys/file.h> /* for flock() */
#include <sys/types.h> /* for open() */
#include <sys/stat.h>
-#if HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#include <unistd.h>
-
+#include "gl_hash_set.h"
+#include "gl_xset.h"
#include "stat-time.h"
#include "timespec.h"
#include "manconfig.h"
#include "error.h"
-#include "hashtable.h"
+#include "glcontainers.h"
#include "mydbm.h"
#include "db_storage.h"
-struct hashtable *loop_check_hash;
+gl_set_t loop_check;
/* the Berkeley database libraries do nothing to arbitrate between concurrent
database accesses, so we do a simple flock(). If the db is opened in
@@ -182,26 +180,27 @@ int btree_exists (DB *db, datum key)
static datum btree_findkey (DB *db, u_int flags)
{
datum key, data;
+ char *loop_check_key;
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
if (flags == R_FIRST) {
- if (loop_check_hash) {
- hashtable_free (loop_check_hash);
- loop_check_hash = NULL;
+ if (loop_check) {
+ gl_set_free (loop_check);
+ loop_check = NULL;
}
}
- if (!loop_check_hash)
- loop_check_hash = hashtable_create (&free);
+ if (!loop_check)
+ loop_check = new_string_set (GL_HASH_SET);
if (((db->seq) (db, (DBT *) &key, (DBT *) &data, flags))) {
memset (&key, 0, sizeof key);
return key;
}
- if (hashtable_lookup (loop_check_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key))) {
+ loop_check_key = xstrndup (MYDBM_DPTR (key), MYDBM_DSIZE (key));
+ if (gl_set_search (loop_check, loop_check_key)) {
/* We've seen this key already, which is broken. Return NULL
* so the caller doesn't go round in circles.
*/
@@ -209,11 +208,11 @@ static datum btree_findkey (DB *db, u_int flags)
"Attempting to recover ...\n",
(int) MYDBM_DSIZE (key), MYDBM_DPTR (key));
memset (&key, 0, sizeof key);
+ free (loop_check_key);
return key;
}
- hashtable_install (loop_check_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key), NULL);
+ gl_set_add (loop_check, loop_check_key);
return copy_datum (key);
}
diff --git a/libdb/db_delete.c b/libdb/db_delete.c
index 4ac6401a..d1e99385 100644
--- a/libdb/db_delete.c
+++ b/libdb/db_delete.c
@@ -30,12 +30,15 @@
#include <stdlib.h>
#include <unistd.h>
+#include "error.h"
+#include "gl_list.h"
+
#include "gettext.h"
#define _(String) gettext (String)
#include "manconfig.h"
-#include "error.h"
+#include "glcontainers.h"
#include "mydbm.h"
#include "db_storage.h"
@@ -74,30 +77,29 @@ int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info)
MYDBM_DELETE (dbf, key);
MYDBM_FREE_DPTR (cont);
} else { /* 2+ entries */
- char **names, **ext;
+ gl_list_t refs;
+ struct name_ext this_ref, *ref;
+ size_t this_index;
char *multi_content = NULL;
datum multi_key;
- int refs, i, j;
/* Extract all of the extensions associated with
this key */
- refs = list_extensions (MYDBM_DPTR (cont) + 1, &names, &ext);
+ refs = list_extensions (MYDBM_DPTR (cont) + 1);
- for (i = 0; i < refs; ++i)
- if (STREQ (names[i], name) &&
- STREQ (ext[i], info->ext))
- break;
+ this_ref.name = name;
+ this_ref.ext = info->ext;
+ this_index = gl_list_indexof (refs, &this_ref);
- if (i >= refs) {
- free (names);
- free (ext);
+ if (this_index == (size_t) -1) {
+ gl_list_free (refs);
MYDBM_FREE_DPTR (cont);
MYDBM_FREE_DPTR (key);
return NO_ENTRY;
}
- multi_key = make_multi_key (names[i], ext[i]);
+ multi_key = make_multi_key (name, info->ext);
if (!MYDBM_EXISTS (dbf, multi_key)) {
error (0, 0,
_( "multi key %s does not exist"),
@@ -106,14 +108,13 @@ int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info)
}
MYDBM_DELETE (dbf, multi_key);
MYDBM_FREE_DPTR (multi_key);
+ gl_list_remove_at (refs, this_index);
- /* refs *may* be 1 if all manual pages with this name
- have been deleted. In this case, we'll have to remove
- the key too */
+ /* If all manual pages with this name have been deleted,
+ we'll have to remove the key too. */
- if (refs == 1) {
- free (names);
- free (ext);
+ if (!gl_list_size (refs)) {
+ gl_list_free (refs);
MYDBM_FREE_DPTR (cont);
MYDBM_DELETE (dbf, key);
MYDBM_FREE_DPTR (key);
@@ -121,26 +122,19 @@ int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info)
}
/* create our new multi content */
- for (j = 0; j < refs; ++j)
- if (i != j)
- multi_content = appendstr (multi_content,
- "\t", names[j],
- "\t", ext[j],
- (void *) 0);
+ GL_LIST_FOREACH_START (refs, ref)
+ multi_content = appendstr (multi_content,
+ "\t", ref->name,
+ "\t", ref->ext,
+ (void *) 0);
+ GL_LIST_FOREACH_END (refs);
MYDBM_FREE_DPTR (cont);
-
- /* if refs = 2 do something else. Doesn't really matter as
- the gdbm db file does not shrink any after a deletion
- anyway */
-
MYDBM_SET (cont, multi_content);
-
if (MYDBM_REPLACE (dbf, key, cont))
gripe_replace_key (MYDBM_DPTR (key));
- free (names);
- free (ext);
+ gl_list_free (refs);
}
MYDBM_FREE_DPTR (key);
diff --git a/libdb/db_gdbm.c b/libdb/db_gdbm.c
index f3aaa94e..d8fb988d 100644
--- a/libdb/db_gdbm.c
+++ b/libdb/db_gdbm.c
@@ -34,22 +34,22 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "gl_hash_map.h"
+#include "gl_rbtree_list.h"
+#include "gl_xlist.h"
+#include "gl_xmap.h"
+#include "hash-pjw-bare.h"
#include "stat-time.h"
#include "timespec.h"
#include "manconfig.h"
-#include "hashtable.h"
#include "cleanup.h"
+#include "glcontainers.h"
#include "mydbm.h"
-static struct hashtable *parent_sortkey_hash;
-
-struct sortkey {
- datum key;
- struct sortkey *next;
-};
+static gl_map_t parent_keys;
/* setjmp/longjmp handling to defend against _gdbm_fatal exiting under our
* feet. Not thread-safe, but there is no plan for man-db to ever use
@@ -103,129 +103,111 @@ man_gdbm_wrapper man_gdbm_open_wrapper (const char *name, int flags)
return wrap;
}
-static void parent_sortkey_hashtable_free (void *defn)
-{
- /* Automatically free child hashtables on removal. */
- hashtable_free ((struct hashtable *) defn);
-}
-
-static void sortkey_hashtable_free (void *defn)
+static int datum_compare (const void *a, const void *b)
{
- struct sortkey *key = (struct sortkey *) defn;
- MYDBM_FREE_DPTR (key->key);
- free (key);
-}
-
-static int sortkey_compare (const void *a, const void *b)
-{
- const struct sortkey **left = (const struct sortkey **) a;
- const struct sortkey **right = (const struct sortkey **) b;
+ const datum *left = (const datum *) a;
+ const datum *right = (const datum *) b;
int cmp;
size_t minsize;
/* Sentinel NULL elements sort to the end. */
- if (!MYDBM_DPTR ((*left)->key))
+ if (!MYDBM_DPTR (*left))
return 1;
- else if (!MYDBM_DPTR ((*right)->key))
+ else if (!MYDBM_DPTR (*right))
return -1;
- if (MYDBM_DSIZE ((*left)->key) < MYDBM_DSIZE ((*right)->key))
- minsize = MYDBM_DSIZE ((*left)->key);
+ if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right))
+ minsize = MYDBM_DSIZE (*left);
else
- minsize = MYDBM_DSIZE ((*right)->key);
- cmp = strncmp (MYDBM_DPTR ((*left)->key), MYDBM_DPTR ((*right)->key),
- minsize);
+ minsize = MYDBM_DSIZE (*right);
+ cmp = strncmp (MYDBM_DPTR (*left), MYDBM_DPTR (*right), minsize);
if (cmp)
return cmp;
- else if (MYDBM_DSIZE ((*left)->key) < MYDBM_DSIZE ((*right)->key))
+ else if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right))
return 1;
- else if (MYDBM_DSIZE ((*left)->key) > MYDBM_DSIZE ((*right)->key))
+ else if (MYDBM_DSIZE (*left) > MYDBM_DSIZE (*right))
return -1;
else
return 0;
}
+static bool datum_equals (const void *a, const void *b)
+{
+ return datum_compare (a, b) == 0;
+}
+
+static size_t datum_hash (const void *value)
+{
+ const datum *d = value;
+ return hash_pjw_bare (MYDBM_DPTR (*d), MYDBM_DSIZE (*d));
+}
+
+static void datum_free (const void *value)
+{
+ MYDBM_FREE_DPTR (*(datum *) value);
+}
+
static datum empty_datum = { NULL, 0 };
-/* We keep a hashtable of filenames to sorted lists of keys. Each list is
- * stored both with links from each element to the next and in a hashtable,
- * so that both sequential access and random access are quick. This is
- * necessary for a reasonable ordered implementation of nextkey.
+/* We keep a map of filenames to sorted lists of keys. Each list is stored
+ * using a hash-based implementation that allows lookup by name and
+ * traversal to the next item in O(log n) time, which is necessary for a
+ * reasonable ordered implementation of nextkey.
*/
datum man_gdbm_firstkey (man_gdbm_wrapper wrap)
{
- struct hashtable *sortkey_hash;
- struct sortkey **keys, *firstkey;
- int numkeys = 0, maxkeys = 256;
- int i;
-
- /* Build the raw list of keys and sort it. */
- keys = xnmalloc (maxkeys, sizeof *keys);
- keys[0] = xmalloc (sizeof **keys);
- keys[0]->key = gdbm_firstkey (wrap->file);
- while (MYDBM_DPTR (keys[numkeys]->key)) {
- if (++numkeys >= maxkeys) {
- maxkeys *= 2;
- keys = xnrealloc (keys, maxkeys, sizeof *keys);
- }
- keys[numkeys] = xmalloc (sizeof **keys);
- keys[numkeys]->key =
- gdbm_nextkey (wrap->file, keys[numkeys - 1]->key);
+ gl_list_t keys;
+ datum *key;
+
+ /* Build the raw sorted list of keys. */
+ keys = gl_list_create_empty (GL_RBTREE_LIST, datum_equals, datum_hash,
+ datum_free, false);
+ key = XMALLOC (datum);
+ *key = gdbm_firstkey (wrap->file);
+ while (MYDBM_DPTR (*key)) {
+ datum *next;
+
+ gl_sortedlist_add (keys, datum_compare, key);
+ next = XMALLOC (datum);
+ *next = gdbm_nextkey (wrap->file, *key);
+ key = next;
}
- free (keys[numkeys]);
- keys[numkeys] = NULL; /* simplifies the empty case */
- qsort (keys, numkeys, sizeof *keys, &sortkey_compare);
-
- /* Link the elements together and insert them into a hash. */
- sortkey_hash = hashtable_create (&sortkey_hashtable_free);
- for (i = 0; i < numkeys; ++i) {
- if (i < numkeys - 1)
- keys[i]->next = keys[i + 1];
- else
- keys[i]->next = NULL;
- hashtable_install (sortkey_hash,
- MYDBM_DPTR (keys[i]->key),
- MYDBM_DSIZE (keys[i]->key),
- keys[i]);
- }
- firstkey = keys[0];
- free (keys); /* element memory now owned by hashtable */
-
- if (!parent_sortkey_hash) {
- parent_sortkey_hash = hashtable_create
- (&parent_sortkey_hashtable_free);
- push_cleanup ((cleanup_fun) hashtable_free,
- parent_sortkey_hash, 0);
+
+ if (!parent_keys) {
+ parent_keys = new_string_map (GL_HASH_MAP,
+ (gl_listelement_dispose_fn)
+ gl_list_free);
+ push_cleanup ((cleanup_fun) gl_map_free, parent_keys, 0);
}
/* Remember this structure for use by nextkey. */
- hashtable_install (parent_sortkey_hash,
- wrap->name, strlen (wrap->name), sortkey_hash);
+ gl_map_put (parent_keys, xstrdup (wrap->name), keys);
- if (firstkey)
- return copy_datum (firstkey->key);
+ if (gl_list_size (keys))
+ return copy_datum (*(datum *) gl_list_get_at (keys, 0));
else
- return empty_datum; /* dptr is NULL, so no copy needed */
+ return empty_datum;
}
datum man_gdbm_nextkey (man_gdbm_wrapper wrap, datum key)
{
- struct hashtable *sortkey_hash;
- struct sortkey *sortkey;
+ gl_list_t keys;
+ gl_list_node_t node, next_node;
- if (!parent_sortkey_hash)
+ if (!parent_keys)
return empty_datum;
- sortkey_hash = hashtable_lookup (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- if (!sortkey_hash)
+ keys = (gl_list_t) gl_map_get (parent_keys, wrap->name);
+ if (!keys)
return empty_datum;
- sortkey = hashtable_lookup (sortkey_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key));
- if (!sortkey || !sortkey->next)
+ node = gl_sortedlist_search (keys, datum_compare, &key);
+ if (!node)
+ return empty_datum;
+ next_node = gl_list_next_node (keys, node);
+ if (!next_node)
return empty_datum;
- return copy_datum (sortkey->next->key);
+ return copy_datum (*(datum *) gl_list_node_value (keys, next_node));
}
struct timespec man_gdbm_get_time (man_gdbm_wrapper wrap)
@@ -255,14 +237,8 @@ void man_gdbm_close (man_gdbm_wrapper wrap)
if (!wrap)
return;
- if (parent_sortkey_hash) {
- struct hashtable *sortkey_hash =
- hashtable_lookup (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- if (sortkey_hash)
- hashtable_remove (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- }
+ if (parent_keys)
+ gl_map_remove (parent_keys, wrap->name);
free (wrap->name);
gdbm_close (wrap->file);
diff --git a/libdb/db_lookup.c b/libdb/db_lookup.c
index 140a5050..28cd90e2 100644
--- a/libdb/db_lookup.c
+++ b/libdb/db_lookup.c
@@ -26,6 +26,7 @@
# include "config.h"
#endif /* HAVE_CONFIG_H */
+#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
@@ -33,7 +34,10 @@
#include <stdlib.h>
#include <unistd.h>
+#include "error.h"
#include "fnmatch.h"
+#include "gl_array_list.h"
+#include "gl_xlist.h"
#include "regex.h"
#include "xvasprintf.h"
@@ -42,8 +46,7 @@
#include "manconfig.h"
-#include "error.h"
-#include "lower.h"
+#include "glcontainers.h"
#include "wordfnmatch.h"
#include "xregcomp.h"
@@ -145,19 +148,12 @@ void free_mandata_elements (struct mandata *pinfo)
free (pinfo->name); /* free the real name */
}
-/* Go through the linked list of structures, free()ing the 'content' and the
- * structs themselves.
- */
+/* Free a mandata structure and its elements. */
void free_mandata_struct (struct mandata *pinfo)
{
- while (pinfo) {
- struct mandata *next;
-
- next = pinfo->next;
+ if (pinfo)
free_mandata_elements (pinfo);
- free (pinfo); /* free the structure */
- pinfo = next;
- }
+ free (pinfo);
}
/* Get the key that should be used for a given name. The caller is
@@ -165,7 +161,13 @@ void free_mandata_struct (struct mandata *pinfo)
*/
char *name_to_key (const char *name)
{
- return lower (name);
+ char *low, *p;
+
+ p = low = xmalloc (strlen (name) + 1);
+ while (*name)
+ *p++ = CTYPE (tolower, *name++);
+ *p = *name;
+ return low;
}
/* return char ptr array to the data's fields */
@@ -218,39 +220,43 @@ void split_content (char *cont_ptr, struct mandata *pinfo)
pinfo->whatis = *(data);
pinfo->addr = cont_ptr;
- pinfo->next = (struct mandata *) NULL;
+}
+
+static bool name_ext_equals (const void *elt1, const void *elt2)
+{
+ const struct name_ext *ref1 = elt1, *ref2 = elt2;
+ return STREQ (ref1->name, ref2->name) && STREQ (ref1->ext, ref2->ext);
}
/* Extract all of the names/extensions associated with this key. Each case
* variant of a name will be returned separately.
*
- * names and ext should be pointers to valid memory which will be filled in
- * with the address of the allocated arrays of names and extensions. The
- * caller is expected to free these arrays.
+ * This returns a newly-allocated list of struct name_ext, which the caller
+ * is expected to free.
*/
-int list_extensions (char *data, char ***names, char ***ext)
+gl_list_t list_extensions (char *data)
{
- int count = 0;
- int bound = 4; /* most multi keys will have fewer than this */
-
- *names = xnmalloc (bound, sizeof **names);
- *ext = xnmalloc (bound, sizeof **ext);
- while (((*names)[count] = strsep (&data, "\t")) != NULL) {
- (*ext)[count] = strsep (&data, "\t");
- if ((*ext)[count])
- ++count;
- else
+ gl_list_t list = gl_list_create_empty (GL_ARRAY_LIST, name_ext_equals,
+ NULL, plain_free, true);
+ char *name;
+
+ while ((name = strsep (&data, "\t")) != NULL) {
+ char *ext;
+ struct name_ext *name_ext;
+
+ ext = strsep (&data, "\t");
+ if (!ext)
break;
- if (count >= bound) {
- bound *= 2;
- *names = xnrealloc (*names, bound, sizeof **names);
- *ext = xnrealloc (*ext, bound, sizeof **ext);
- }
+ name_ext = XMALLOC (struct name_ext);
+ /* Don't copy these; they will point into the given string. */
+ name_ext->name = name;
+ name_ext->ext = ext;
+ gl_list_add_last (list, name_ext);
}
- debug ("found %d names/extensions\n", count);
- return count;
+ debug ("found %zd names/extensions\n", gl_list_size (list));
+ return list;
}
/* These should be bitwise-ored together. */
@@ -261,16 +267,22 @@ int list_extensions (char *data, char ***names, char ***ext)
/*
There are three possibilities on lookup:
- 1) No data exists, lookup will fail, returned structure will be NULL.
- 2) One data item exists. Item is returned as first in set of structures.
- 3) Many items exist. They are all returned, in a multiple structure set.
+ 1) No data exists, lookup will fail, zero-length list will be returned.
+ 2) One data item exists. Item is returned as first in list of structures.
+ 3) Many items exist. They are all returned, in a multiple structure list.
*/
-static struct mandata *dblookup (MYDBM_FILE dbf, const char *page,
- const char *section, int flags)
+static gl_list_t dblookup (MYDBM_FILE dbf, const char *page,
+ const char *section, int flags)
{
+ gl_list_t infos;
struct mandata *info = NULL;
datum key, cont;
+ infos = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL,
+ (gl_listelement_dispose_fn)
+ free_mandata_struct,
+ true);
+
memset (&key, 0, sizeof key);
memset (&cont, 0, sizeof cont);
@@ -278,41 +290,44 @@ static struct mandata *dblookup (MYDBM_FILE dbf, const char *page,
cont = MYDBM_FETCH (dbf, key);
MYDBM_FREE_DPTR (key);
- if (MYDBM_DPTR (cont) == NULL) { /* No entries at all */
- return info; /* indicate no entries */
- } else if (*MYDBM_DPTR (cont) != '\t') { /* Just one entry */
+ if (MYDBM_DPTR (cont) == NULL) /* No entries at all */
+ ;
+ else if (*MYDBM_DPTR (cont) != '\t') { /* Just one entry */
+ bool matches = false;
+
info = infoalloc ();
split_content (MYDBM_DPTR (cont), info);
if (!info->name)
info->name = xstrdup (page);
if (!(flags & MATCH_CASE) || STREQ (info->name, page)) {
if (section == NULL)
- return info;
- if (flags & EXACT) {
+ matches = true;
+ else if (flags & EXACT) {
if (STREQ (section, info->ext))
- return info;
+ matches = true;
} else {
if (STRNEQ (section, info->ext,
strlen (section)))
- return info;
+ matches = true;
}
}
- free_mandata_struct (info);
- return NULL;
- } else { /* multiple entries */
- char **names, **ext;
- struct mandata *ret = NULL;
- int refs, i;
+ if (matches)
+ gl_list_add_last (infos, info);
+ else
+ free_mandata_struct (info);
+ } else { /* Multiple entries */
+ gl_list_t refs;
+ struct name_ext *ref;
/* Extract all of the case-variant-names/extensions
* associated with this key.
*/
- refs = list_extensions (MYDBM_DPTR (cont) + 1, &names, &ext);
+ refs = list_extensions (MYDBM_DPTR (cont) + 1);
/* Make the multi keys and look them up */
- for (i = 0; i < refs; ++i) {
+ GL_LIST_FOREACH_START (refs, ref) {
datum multi_cont;
memset (&multi_cont, 0, sizeof multi_cont);
@@ -321,22 +336,22 @@ static struct mandata *dblookup (MYDBM_FILE dbf, const char *page,
* suitable.
*/
- if ((flags & MATCH_CASE) && !STREQ (names[i], page))
+ if ((flags & MATCH_CASE) && !STREQ (ref->name, page))
continue;
if (section != NULL) {
if (flags & EXACT) {
- if (!STREQ (section, ext[i]))
+ if (!STREQ (section, ref->ext))
continue;
} else {
- if (!STRNEQ (section, ext[i],
+ if (!STRNEQ (section, ref->ext,
strlen (section)))
continue;
}
}
/* So the key is suitable ... */
- key = make_multi_key (names[i], ext[i]);
+ key = make_multi_key (ref->name, ref->ext);
debug ("multi key lookup (%s)\n", MYDBM_DPTR (key));
multi_cont = MYDBM_FETCH (dbf, key);
if (MYDBM_DPTR (multi_cont) == NULL) {
@@ -346,46 +361,58 @@ static struct mandata *dblookup (MYDBM_FILE dbf, const char *page,
}
MYDBM_FREE_DPTR (key);
- /* allocate info struct, fill it in and
- point info to the next in the list */
- if (!ret)
- ret = info = infoalloc ();
- else
- info = info->next = infoalloc ();
+ /* Allocate info struct and add it to the list. */
+ info = infoalloc ();
split_content (MYDBM_DPTR (multi_cont), info);
if (!info->name)
- info->name = xstrdup (names[i]);
- }
+ info->name = xstrdup (ref->name);
+ gl_list_add_last (infos, info);
+ } GL_LIST_FOREACH_END (refs);
- free (names);
- free (ext);
+ gl_list_free (refs);
MYDBM_FREE_DPTR (cont);
- return ret;
}
+
+ return infos;
}
-struct mandata *dblookup_all (MYDBM_FILE dbf, const char *page,
- const char *section, int match_case)
+gl_list_t dblookup_all (MYDBM_FILE dbf, const char *page,
+ const char *section, bool match_case)
{
return dblookup (dbf, page, section,
ALL | (match_case ? MATCH_CASE : 0));
}
struct mandata *dblookup_exact (MYDBM_FILE dbf, const char *page,
- const char *section, int match_case)
+ const char *section, bool match_case)
{
- return dblookup (dbf, page, section,
- EXACT | (match_case ? MATCH_CASE : 0));
+ gl_list_t infos = dblookup (dbf, page, section,
+ EXACT | (match_case ? MATCH_CASE : 0));
+ struct mandata *info = NULL;
+
+ if (gl_list_size (infos)) {
+ /* Return the first item and free the rest of the list. */
+ info = (struct mandata *) gl_list_get_at (infos, 0);
+ gl_list_set_at (infos, 0, NULL); /* steal memory */
+ }
+ gl_list_free (infos);
+ return info;
}
-struct mandata *dblookup_pattern (MYDBM_FILE dbf, const char *pattern,
- const char *section, int match_case,
- int pattern_regex, int try_descriptions)
+gl_list_t dblookup_pattern (MYDBM_FILE dbf, const char *pattern,
+ const char *section, bool match_case,
+ bool pattern_regex, bool try_descriptions)
{
- struct mandata *ret = NULL, *tail = NULL;
+ gl_list_t infos;
+ struct mandata *tail = NULL;
datum key, cont;
regex_t preg;
+ infos = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL,
+ (gl_listelement_dispose_fn)
+ free_mandata_struct,
+ true);
+
if (pattern_regex)
xregcomp (&preg, pattern,
REG_EXTENDED | REG_NOSUB |
@@ -405,7 +432,7 @@ struct mandata *dblookup_pattern (MYDBM_FILE dbf, const char *pattern,
#endif /* !BTREE */
struct mandata info;
char *tab;
- int got_match;
+ bool got_match;
memset (&info, 0, sizeof (info));
@@ -460,13 +487,11 @@ struct mandata *dblookup_pattern (MYDBM_FILE dbf, const char *pattern,
if (!got_match)
goto nextpage_tab;
- if (!ret)
- ret = tail = infoalloc ();
- else
- tail = tail->next = infoalloc ();
+ tail = infoalloc ();
memcpy (tail, &info, sizeof (info));
info.name = NULL; /* steal memory */
MYDBM_SET_DPTR (cont, NULL); /* == info.addr */
+ gl_list_add_last (infos, tail);
nextpage_tab:
if (tab)
@@ -489,5 +514,5 @@ nextpage:
if (pattern_regex)
regfree (&preg);
- return ret;
+ return infos;
}
diff --git a/libdb/db_ndbm.c b/libdb/db_ndbm.c
index af970322..992173ae 100644
--- a/libdb/db_ndbm.c
+++ b/libdb/db_ndbm.c
@@ -28,17 +28,13 @@
#include <stdlib.h>
#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <sys/file.h> /* for flock() */
#include <sys/types.h> /* for open() */
#include <sys/stat.h>
-#if HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#include <unistd.h>
-
#include "stat-time.h"
#include "timespec.h"
#include "xvasprintf.h"
diff --git a/libdb/db_storage.h b/libdb/db_storage.h
index 6db37bb7..a04196bc 100644
--- a/libdb/db_storage.h
+++ b/libdb/db_storage.h
@@ -26,6 +26,8 @@
#ifndef DB_STORAGE_H
#define DB_STORAGE_H
+#include "gl_list.h"
+
/* These definitions give an inherent precedence to each particular type
of manual page:
@@ -52,7 +54,6 @@
#include "mydbm.h"
struct mandata {
- struct mandata *next; /* ptr to next structure, if any */
char *addr; /* ptr to memory containing the fields */
char *name; /* Name of page, if != key */
@@ -71,15 +72,19 @@ struct mandata {
struct timespec mtime; /* mod time for file */
};
+struct name_ext {
+ const char *name;
+ const char *ext;
+};
+
/* used by the world */
-extern struct mandata *dblookup_all (MYDBM_FILE dbf, const char *page,
- const char *section, int match_case);
+extern gl_list_t dblookup_all (MYDBM_FILE dbf, const char *page,
+ const char *section, bool match_case);
extern struct mandata *dblookup_exact (MYDBM_FILE dbf, const char *page,
- const char *section, int match_case);
-extern struct mandata *dblookup_pattern (MYDBM_FILE dbf, const char *page,
- const char *section, int match_case,
- int pattern_regex,
- int try_descriptions);
+ const char *section, bool match_case);
+extern gl_list_t dblookup_pattern (MYDBM_FILE dbf, const char *page,
+ const char *section, bool match_case,
+ bool pattern_regex, bool try_descriptions);
extern int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base);
extern int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *in);
extern void dbprintf (const struct mandata *info);
@@ -97,7 +102,8 @@ extern datum make_multi_key (const char *page, const char *ext);
#define infoalloc() XZALLOC (struct mandata)
extern char *name_to_key (const char *name);
-extern int list_extensions (char *data, char ***names, char ***ext);
+/* Returns a list of struct name_ext. */
+extern gl_list_t list_extensions (char *data);
extern void gripe_replace_key (const char *data);
extern const char *dash_if_unset (const char *str);
diff --git a/libdb/mydbm.h b/libdb/mydbm.h
index 567e96ad..32053e3e 100644
--- a/libdb/mydbm.h
+++ b/libdb/mydbm.h
@@ -90,12 +90,9 @@ void man_gdbm_close (man_gdbm_wrapper wrap);
# elif defined(NDBM) && !defined(GDBM) && !defined(BTREE)
+# include <fcntl.h>
# include <ndbm.h>
-# if HAVE_FCNTL_H
-# include <fcntl.h>
-# endif
-
/* Berkeley db routines emulate ndbm but don't add .dir & .pag, just .db! */
# ifdef _DB_H_ /* has Berkeley db.h been included? */
# define BERKELEY_DB