diff options
author | Colin Watson <cjwatson@debian.org> | 2019-08-03 12:15:34 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-08-03 12:15:34 +0100 |
commit | f22ec2853f6ea2123dc4a1fee566a828e8d86bc6 (patch) | |
tree | b4d8e7309d6d25acee9b3a94f6e07acb209daacd /libdb | |
parent | 182141146d0ad9c735949840504bdfc66332da4e (diff) | |
parent | 74d8f72dc1ca9620d3e8e1ae2ed9b19047ba348f (diff) |
Import man-db_2.8.6.orig.tar.xz
Diffstat (limited to 'libdb')
-rw-r--r-- | libdb/Makefile.in | 5 | ||||
-rw-r--r-- | libdb/db_btree.c | 33 | ||||
-rw-r--r-- | libdb/db_delete.c | 58 | ||||
-rw-r--r-- | libdb/db_gdbm.c | 176 | ||||
-rw-r--r-- | libdb/db_lookup.c | 195 | ||||
-rw-r--r-- | libdb/db_ndbm.c | 8 | ||||
-rw-r--r-- | libdb/db_storage.h | 24 | ||||
-rw-r--r-- | libdb/mydbm.h | 5 |
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 |