diff options
author | Colin Watson <cjwatson@debian.org> | 2019-08-26 16:24:25 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-08-26 16:24:25 +0100 |
commit | 4022480a2cbcd303c5fcb3547dab2896ae1915a9 (patch) | |
tree | aa7f325ed783df7e253f8474df7121c6f1f85ea2 /libdb | |
parent | 886374b96c0da5287b5a9eba5777cb2d9f0ea3d8 (diff) | |
parent | 1c9cb89a74a0e54309eff01adcac9775e8c0563a (diff) |
Import man-db_2.8.7.orig.tar.xz
Diffstat (limited to 'libdb')
-rw-r--r-- | libdb/Makefile.am | 2 | ||||
-rw-r--r-- | libdb/Makefile.in | 34 | ||||
-rw-r--r-- | libdb/db_btree.c | 90 | ||||
-rw-r--r-- | libdb/db_delete.c | 4 | ||||
-rw-r--r-- | libdb/db_gdbm.c | 123 | ||||
-rw-r--r-- | libdb/db_lookup.c | 38 | ||||
-rw-r--r-- | libdb/db_ndbm.c | 81 | ||||
-rw-r--r-- | libdb/db_storage.h | 9 | ||||
-rw-r--r-- | libdb/db_store.c | 23 | ||||
-rw-r--r-- | libdb/db_ver.c | 7 | ||||
-rw-r--r-- | libdb/db_xdbm.c | 169 | ||||
-rw-r--r-- | libdb/db_xdbm.h | 40 | ||||
-rw-r--r-- | libdb/mydbm.h | 108 |
13 files changed, 466 insertions, 262 deletions
diff --git a/libdb/Makefile.am b/libdb/Makefile.am index 0015b84b..2851dfa3 100644 --- a/libdb/Makefile.am +++ b/libdb/Makefile.am @@ -39,6 +39,8 @@ libmandb_la_SOURCES = \ db_storage.h \ db_store.c \ db_ver.c \ + db_xdbm.c \ + db_xdbm.h \ mydbm.h libmandb_la_LIBADD = ../lib/libman.la $(DBLIBS) diff --git a/libdb/Makefile.in b/libdb/Makefile.in index afc0b5ea..04607282 100644 --- a/libdb/Makefile.in +++ b/libdb/Makefile.in @@ -184,6 +184,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/gl/m4/ltversion.m4 \ $(top_srcdir)/gl/m4/lt~obsolete.m4 \ $(top_srcdir)/gl/m4/malloc.m4 $(top_srcdir)/gl/m4/malloca.m4 \ + $(top_srcdir)/gl/m4/manywarnings.m4 \ $(top_srcdir)/gl/m4/mbrtowc.m4 $(top_srcdir)/gl/m4/mbsinit.m4 \ $(top_srcdir)/gl/m4/mbsrtowcs.m4 \ $(top_srcdir)/gl/m4/mbstate_t.m4 $(top_srcdir)/gl/m4/mbtowc.m4 \ @@ -301,7 +302,8 @@ libmandb_la_DEPENDENCIES = ../lib/libman.la $(am__DEPENDENCIES_1) am_libmandb_la_OBJECTS = libmandb_la-db_btree.lo \ libmandb_la-db_delete.lo libmandb_la-db_gdbm.lo \ libmandb_la-db_lookup.lo libmandb_la-db_ndbm.lo \ - libmandb_la-db_store.lo libmandb_la-db_ver.lo + libmandb_la-db_store.lo libmandb_la-db_ver.lo \ + libmandb_la-db_xdbm.lo libmandb_la_OBJECTS = $(am_libmandb_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -331,7 +333,8 @@ am__depfiles_remade = ./$(DEPDIR)/libmandb_la-db_btree.Plo \ ./$(DEPDIR)/libmandb_la-db_lookup.Plo \ ./$(DEPDIR)/libmandb_la-db_ndbm.Plo \ ./$(DEPDIR)/libmandb_la-db_store.Plo \ - ./$(DEPDIR)/libmandb_la-db_ver.Plo + ./$(DEPDIR)/libmandb_la-db_ver.Plo \ + ./$(DEPDIR)/libmandb_la-db_xdbm.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -447,6 +450,7 @@ GNULIB_CHOWN = @GNULIB_CHOWN@ GNULIB_CLOSE = @GNULIB_CLOSE@ GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ GNULIB_CONNECT = @GNULIB_CONNECT@ +GNULIB_COPY_FILE_RANGE = @GNULIB_COPY_FILE_RANGE@ GNULIB_CTIME = @GNULIB_CTIME@ GNULIB_DIRFD = @GNULIB_DIRFD@ GNULIB_DPRINTF = @GNULIB_DPRINTF@ @@ -654,6 +658,7 @@ GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ GNULIB_STRSTR = @GNULIB_STRSTR@ GNULIB_STRTOD = @GNULIB_STRTOD@ GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLD = @GNULIB_STRTOLD@ GNULIB_STRTOLL = @GNULIB_STRTOLL@ GNULIB_STRTOULL = @GNULIB_STRTOULL@ GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ @@ -728,6 +733,7 @@ GNULIB_WRITE = @GNULIB_WRITE@ GNULIB__EXIT = @GNULIB__EXIT@ GREP = @GREP@ HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ HAVE_ALPHASORT = @HAVE_ALPHASORT@ HAVE_ATOLL = @HAVE_ATOLL@ HAVE_BTOWC = @HAVE_BTOWC@ @@ -735,6 +741,7 @@ HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ HAVE_CHOWN = @HAVE_CHOWN@ HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ HAVE_CRTDEFS_H = @HAVE_CRTDEFS_H@ HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ @@ -816,6 +823,7 @@ HAVE_GLOB_H = @HAVE_GLOB_H@ HAVE_GLOB_PATTERN_P = @HAVE_GLOB_PATTERN_P@ HAVE_GRANTPT = @HAVE_GRANTPT@ HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_INITSTATE = @HAVE_INITSTATE@ HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ HAVE_ISWBLANK = @HAVE_ISWBLANK@ HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ @@ -838,6 +846,7 @@ HAVE_MBSINIT = @HAVE_MBSINIT@ HAVE_MBSLEN = @HAVE_MBSLEN@ HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MBTOWC = @HAVE_MBTOWC@ HAVE_MEMCHR = @HAVE_MEMCHR@ HAVE_MEMPCPY = @HAVE_MEMPCPY@ HAVE_MKDIRAT = @HAVE_MKDIRAT@ @@ -888,6 +897,7 @@ HAVE_SCANDIR = @HAVE_SCANDIR@ HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ HAVE_SETENV = @HAVE_SETENV@ HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SETSTATE = @HAVE_SETSTATE@ HAVE_SIGACTION = @HAVE_SIGACTION@ HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ @@ -907,6 +917,7 @@ HAVE_STRPBRK = @HAVE_STRPBRK@ HAVE_STRPTIME = @HAVE_STRPTIME@ HAVE_STRSEP = @HAVE_STRSEP@ HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLD = @HAVE_STRTOLD@ HAVE_STRTOLL = @HAVE_STRTOLL@ HAVE_STRTOULL = @HAVE_STRTOULL@ HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ @@ -1007,8 +1018,6 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBMULTITHREAD = @LIBMULTITHREAD@ LIBOBJS = @LIBOBJS@ -LIBPTH = @LIBPTH@ -LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBSOCKET = @LIBSOCKET@ LIBTHREAD = @LIBTHREAD@ @@ -1031,7 +1040,6 @@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ LTLIBOBJS = @LTLIBOBJS@ -LTLIBPTH = @LTLIBPTH@ LTLIBTHREAD = @LTLIBTHREAD@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ @@ -1177,6 +1185,7 @@ REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ REPLACE_GLOB = @REPLACE_GLOB@ REPLACE_GLOB_PATTERN_P = @REPLACE_GLOB_PATTERN_P@ REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_INITSTATE = @REPLACE_INITSTATE@ REPLACE_IOCTL = @REPLACE_IOCTL@ REPLACE_ISATTY = @REPLACE_ISATTY@ REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ @@ -1225,6 +1234,7 @@ REPLACE_PUTENV = @REPLACE_PUTENV@ REPLACE_PWRITE = @REPLACE_PWRITE@ REPLACE_QSORT_R = @REPLACE_QSORT_R@ REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM = @REPLACE_RANDOM@ REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ REPLACE_READ = @REPLACE_READ@ REPLACE_READLINK = @REPLACE_READLINK@ @@ -1238,6 +1248,7 @@ REPLACE_RMDIR = @REPLACE_RMDIR@ REPLACE_SELECT = @REPLACE_SELECT@ REPLACE_SETENV = @REPLACE_SETENV@ REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SETSTATE = @REPLACE_SETSTATE@ REPLACE_SLEEP = @REPLACE_SLEEP@ REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ REPLACE_SPRINTF = @REPLACE_SPRINTF@ @@ -1258,6 +1269,7 @@ REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ REPLACE_STRSTR = @REPLACE_STRSTR@ REPLACE_STRTOD = @REPLACE_STRTOD@ REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOLD = @REPLACE_STRTOLD@ REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ REPLACE_SYMLINK = @REPLACE_SYMLINK@ @@ -1464,6 +1476,8 @@ libmandb_la_SOURCES = \ db_storage.h \ db_store.c \ db_ver.c \ + db_xdbm.c \ + db_xdbm.h \ mydbm.h libmandb_la_LIBADD = ../lib/libman.la $(DBLIBS) @@ -1555,6 +1569,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmandb_la-db_ndbm.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmandb_la-db_store.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmandb_la-db_ver.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmandb_la-db_xdbm.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1632,6 +1647,13 @@ libmandb_la-db_ver.lo: db_ver.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmandb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmandb_la-db_ver.lo `test -f 'db_ver.c' || echo '$(srcdir)/'`db_ver.c +libmandb_la-db_xdbm.lo: db_xdbm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmandb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmandb_la-db_xdbm.lo -MD -MP -MF $(DEPDIR)/libmandb_la-db_xdbm.Tpo -c -o libmandb_la-db_xdbm.lo `test -f 'db_xdbm.c' || echo '$(srcdir)/'`db_xdbm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmandb_la-db_xdbm.Tpo $(DEPDIR)/libmandb_la-db_xdbm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='db_xdbm.c' object='libmandb_la-db_xdbm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmandb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmandb_la-db_xdbm.lo `test -f 'db_xdbm.c' || echo '$(srcdir)/'`db_xdbm.c + mostlyclean-libtool: -rm -f *.lo @@ -1773,6 +1795,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libmandb_la-db_ndbm.Plo -rm -f ./$(DEPDIR)/libmandb_la-db_store.Plo -rm -f ./$(DEPDIR)/libmandb_la-db_ver.Plo + -rm -f ./$(DEPDIR)/libmandb_la-db_xdbm.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1825,6 +1848,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libmandb_la-db_ndbm.Plo -rm -f ./$(DEPDIR)/libmandb_la-db_store.Plo -rm -f ./$(DEPDIR)/libmandb_la-db_ver.Plo + -rm -f ./$(DEPDIR)/libmandb_la-db_xdbm.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/libdb/db_btree.c b/libdb/db_btree.c index b4e426cc..917e286c 100644 --- a/libdb/db_btree.c +++ b/libdb/db_btree.c @@ -61,16 +61,22 @@ gl_set_t loop_check; blocking method is used ": Try again". This adopts GNU dbm's approach. */ /* release the lock and close the database */ -int btree_close (DB *db) +void man_btree_close (man_btree_wrapper wrap) { - (void) flock ((db->fd) (db), LOCK_UN); - return (db->close) (db); + if (!wrap) + return; + + free (wrap->name); + (void) flock ((wrap->file->fd) (wrap->file), LOCK_UN); + (wrap->file->close) (wrap->file); + free (wrap); } /* open a btree type database, with file locking. */ -DB *btree_flopen (char *filename, int flags, int mode) +man_btree_wrapper man_btree_open (const char *name, int flags, int mode) { - DB *db; + man_btree_wrapper wrap; + DB *file; BTREEINFO b; int lock_op; int lock_failed; @@ -102,7 +108,7 @@ DB *btree_flopen (char *filename, int flags, int mode) * and ignore the database if it's zero-length. */ struct stat iszero; - if (stat (filename, &iszero) < 0) + if (stat (name, &iszero) < 0) return NULL; if (iszero.st_size == 0) { errno = EINVAL; @@ -114,54 +120,59 @@ DB *btree_flopen (char *filename, int flags, int mode) /* opening the db is destructive, need to lock first */ int fd; - db = NULL; + file = NULL; lock_failed = 1; - fd = open (filename, flags & ~O_TRUNC, mode); + fd = open (name, flags & ~O_TRUNC, mode); if (fd != -1) { if (!(lock_failed = flock (fd, lock_op))) - db = dbopen (filename, flags, mode, - DB_BTREE, &b); + file = dbopen (name, flags, mode, + DB_BTREE, &b); close (fd); } } else { - db = dbopen (filename, flags, mode, DB_BTREE, &b); - if (db) - lock_failed = flock ((db->fd) (db), lock_op); + file = dbopen (name, flags, mode, DB_BTREE, &b); + if (file) + lock_failed = flock ((file->fd) (file), lock_op); } - if (!db) + if (!file) return NULL; if (lock_failed) { - gripe_lock (filename); - btree_close (db); + gripe_lock (name); + (file->close) (file); return NULL; } - return db; + wrap = xmalloc (sizeof *wrap); + wrap->name = xstrdup (name); + wrap->file = file; + + return wrap; } /* do a replace when we have the duplicate flag set on the database - we must do a del and insert, as a direct insert will not wipe out the old entry */ -int btree_replace (DB *db, datum key, datum cont) +int man_btree_replace (man_btree_wrapper wrap, datum key, datum cont) { - return (db->put) (db, (DBT *) &key, (DBT *) &cont, 0); + return (wrap->file->put) (wrap->file, (DBT *) &key, (DBT *) &cont, 0); } -int btree_insert (DB *db, datum key, datum cont) +int man_btree_insert (man_btree_wrapper wrap, datum key, datum cont) { - return (db->put) (db, (DBT *) &key, (DBT *) &cont, R_NOOVERWRITE); + return (wrap->file->put) (wrap->file, (DBT *) &key, (DBT *) &cont, + R_NOOVERWRITE); } /* generic fetch routine for the btree database */ -datum btree_fetch (DB *db, datum key) +datum man_btree_fetch (man_btree_wrapper wrap, datum key) { datum data; memset (&data, 0, sizeof data); - if ((db->get) (db, (DBT *) &key, (DBT *) &data, 0)) { + if ((wrap->file->get) (wrap->file, (DBT *) &key, (DBT *) &data, 0)) { memset (&data, 0, sizeof data); return data; } @@ -170,14 +181,15 @@ datum btree_fetch (DB *db, datum key) } /* return 1 if the key exists, 0 otherwise */ -int btree_exists (DB *db, datum key) +int man_btree_exists (man_btree_wrapper wrap, datum key) { datum data; - return ((db->get) (db, (DBT *) &key, (DBT *) &data, 0) ? 0 : 1); + return ((wrap->file->get) (wrap->file, (DBT *) &key, (DBT *) &data, + 0) ? 0 : 1); } /* initiate a sequential access */ -static datum btree_findkey (DB *db, u_int flags) +static datum man_btree_findkey (man_btree_wrapper wrap, u_int flags) { datum key, data; char *loop_check_key; @@ -194,7 +206,8 @@ static datum btree_findkey (DB *db, u_int flags) if (!loop_check) loop_check = new_string_set (GL_HASH_SET); - if (((db->seq) (db, (DBT *) &key, (DBT *) &data, flags))) { + if (((wrap->file->seq) (wrap->file, (DBT *) &key, (DBT *) &data, + flags))) { memset (&key, 0, sizeof key); return key; } @@ -218,26 +231,27 @@ static datum btree_findkey (DB *db, u_int flags) } /* return the first key in the db */ -datum btree_firstkey (DB *db) +datum man_btree_firstkey (man_btree_wrapper wrap) { - return btree_findkey (db, R_FIRST); + return man_btree_findkey (wrap, R_FIRST); } /* return the next key in the db. NB. This routine only works if the cursor - has been previously set by btree_firstkey() since it was last opened. So + has been previously set by man_btree_firstkey() since it was last opened. So if we close/reopen a db mid search, we have to manually set up the cursor again. */ -datum btree_nextkey (DB *db) +datum man_btree_nextkey (man_btree_wrapper wrap) { - return btree_findkey (db, R_NEXT); + return man_btree_findkey (wrap, R_NEXT); } /* compound nextkey routine, initialising key and content */ -int btree_nextkeydata (DB *db, datum *key, datum *cont) +int man_btree_nextkeydata (man_btree_wrapper wrap, datum *key, datum *cont) { int status; - if ((status = (db->seq) (db, (DBT *) key, (DBT *) cont, R_NEXT)) != 0) + if ((status = (wrap->file->seq) (wrap->file, (DBT *) key, (DBT *) cont, + R_NEXT)) != 0) return status; *key = copy_datum (*key); @@ -246,11 +260,11 @@ int btree_nextkeydata (DB *db, datum *key, datum *cont) return 0; } -struct timespec btree_get_time (DB *db) +struct timespec man_btree_get_time (man_btree_wrapper wrap) { struct stat st; - if (fstat ((db->fd) (db), &st) < 0) { + if (fstat ((wrap->file->fd) (wrap->file), &st) < 0) { struct timespec t; t.tv_sec = -1; t.tv_nsec = -1; @@ -259,13 +273,13 @@ struct timespec btree_get_time (DB *db) return get_stat_mtime (&st); } -void btree_set_time (DB *db, const struct timespec time) +void man_btree_set_time (man_btree_wrapper wrap, const struct timespec time) { struct timespec times[2]; times[0] = time; times[1] = time; - futimens ((db->fd) (db), times); + futimens ((wrap->file->fd) (wrap->file), times); } #endif /* BTREE */ diff --git a/libdb/db_delete.c b/libdb/db_delete.c index d1e99385..24ce1d83 100644 --- a/libdb/db_delete.c +++ b/libdb/db_delete.c @@ -104,7 +104,7 @@ int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info) error (0, 0, _( "multi key %s does not exist"), MYDBM_DPTR (multi_key)); - gripe_corrupt_data (); + gripe_corrupt_data (dbf); } MYDBM_DELETE (dbf, multi_key); MYDBM_FREE_DPTR (multi_key); @@ -132,7 +132,7 @@ int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info) MYDBM_FREE_DPTR (cont); MYDBM_SET (cont, multi_content); if (MYDBM_REPLACE (dbf, key, cont)) - gripe_replace_key (MYDBM_DPTR (key)); + gripe_replace_key (dbf, MYDBM_DPTR (key)); gl_list_free (refs); } diff --git a/libdb/db_gdbm.c b/libdb/db_gdbm.c index d8fb988d..1062f357 100644 --- a/libdb/db_gdbm.c +++ b/libdb/db_gdbm.c @@ -34,23 +34,16 @@ #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 "cleanup.h" -#include "glcontainers.h" +#include "db_xdbm.h" #include "mydbm.h" -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 * threads. @@ -103,111 +96,24 @@ man_gdbm_wrapper man_gdbm_open_wrapper (const char *name, int flags) return wrap; } -static int datum_compare (const void *a, const void *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)) - return 1; - else if (!MYDBM_DPTR (*right)) - return -1; - - if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right)) - minsize = MYDBM_DSIZE (*left); - else - minsize = MYDBM_DSIZE (*right); - cmp = strncmp (MYDBM_DPTR (*left), MYDBM_DPTR (*right), minsize); - if (cmp) - return cmp; - else if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right)) - return 1; - else if (MYDBM_DSIZE (*left) > MYDBM_DSIZE (*right)) - return -1; - else - return 0; -} - -static bool datum_equals (const void *a, const void *b) +static datum unsorted_firstkey (man_gdbm_wrapper wrap) { - return datum_compare (a, b) == 0; + return gdbm_firstkey (wrap->file); } -static size_t datum_hash (const void *value) +static datum unsorted_nextkey (man_gdbm_wrapper wrap, datum key) { - const datum *d = value; - return hash_pjw_bare (MYDBM_DPTR (*d), MYDBM_DSIZE (*d)); + return gdbm_nextkey (wrap->file, key); } -static void datum_free (const void *value) -{ - MYDBM_FREE_DPTR (*(datum *) value); -} - -static datum empty_datum = { NULL, 0 }; - -/* 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) { - 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; - } - - 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. */ - gl_map_put (parent_keys, xstrdup (wrap->name), keys); - - if (gl_list_size (keys)) - return copy_datum (*(datum *) gl_list_get_at (keys, 0)); - else - return empty_datum; + return man_xdbm_firstkey (wrap, unsorted_firstkey, unsorted_nextkey); } datum man_gdbm_nextkey (man_gdbm_wrapper wrap, datum key) { - gl_list_t keys; - gl_list_node_t node, next_node; - - if (!parent_keys) - return empty_datum; - keys = (gl_list_t) gl_map_get (parent_keys, wrap->name); - if (!keys) - return empty_datum; - - 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 (*(datum *) gl_list_node_value (keys, next_node)); + return man_xdbm_nextkey (wrap, key); } struct timespec man_gdbm_get_time (man_gdbm_wrapper wrap) @@ -232,17 +138,14 @@ void man_gdbm_set_time (man_gdbm_wrapper wrap, const struct timespec time) futimens (gdbm_fdesc (wrap->file), times); } -void man_gdbm_close (man_gdbm_wrapper wrap) +static void raw_close (man_gdbm_wrapper wrap) { - if (!wrap) - return; - - if (parent_keys) - gl_map_remove (parent_keys, wrap->name); - - free (wrap->name); gdbm_close (wrap->file); - free (wrap); +} + +void man_gdbm_close (man_gdbm_wrapper wrap) +{ + man_xdbm_close (wrap, raw_close); } #ifndef HAVE_GDBM_EXISTS diff --git a/libdb/db_lookup.c b/libdb/db_lookup.c index 28cd90e2..9ff72d6c 100644 --- a/libdb/db_lookup.c +++ b/libdb/db_lookup.c @@ -70,23 +70,23 @@ datum copy_datum (datum dat) /* gdbm does locking itself. */ #if defined(NDBM) || defined(BTREE) -void gripe_lock (char *filename) +void gripe_lock (const char *filename) { error (0, errno, _("can't lock index cache %s"), filename); } #endif /* NDBM || BTREE */ /* issue fatal message, then exit */ -void gripe_corrupt_data (void) +void gripe_corrupt_data (MYDBM_FILE dbf) { - error (FATAL, 0, _("index cache %s corrupt"), database); + error (FATAL, 0, _("index cache %s corrupt"), dbf->name); } /* deal with situation where we cannot replace a key */ -void gripe_replace_key (const char *data) +void gripe_replace_key (MYDBM_FILE dbf, const char *data) { error (0, 0, _("cannot replace key %s"), data); - gripe_corrupt_data (); + gripe_corrupt_data (dbf); } static char *copy_if_set (const char *str) @@ -97,7 +97,7 @@ static char *copy_if_set (const char *str) return xstrdup (str); } -const char *dash_if_unset (const char *str) +const char * _GL_ATTRIBUTE_CONST dash_if_unset (const char *str) { if (str) return str; @@ -171,7 +171,7 @@ char *name_to_key (const char *name) } /* return char ptr array to the data's fields */ -static char **split_data (char *content, char *start[]) +static char **split_data (MYDBM_FILE dbf, char *content, char *start[]) { int count; @@ -183,7 +183,7 @@ static char **split_data (char *content, char *start[]) ngettext ("only %d field in content", "only %d fields in content", count), count); - gripe_corrupt_data (); + gripe_corrupt_data (dbf); } } @@ -194,19 +194,19 @@ static char **split_data (char *content, char *start[]) ngettext ("only %d field in content", "only %d fields in content", FIELDS - 1), FIELDS - 1); - gripe_corrupt_data (); + gripe_corrupt_data (dbf); } return start; } /* Parse the db-returned data and put it into a mandata format */ -void split_content (char *cont_ptr, struct mandata *pinfo) +void split_content (MYDBM_FILE dbf, char *cont_ptr, struct mandata *pinfo) { char *start[FIELDS]; char **data; - data = split_data (cont_ptr, start); + data = split_data (dbf, cont_ptr, start); pinfo->name = copy_if_set (*(data++)); pinfo->ext = *(data++); @@ -255,7 +255,7 @@ gl_list_t list_extensions (char *data) gl_list_add_last (list, name_ext); } - debug ("found %zd names/extensions\n", gl_list_size (list)); + debug ("found %zu names/extensions\n", gl_list_size (list)); return list; } @@ -296,7 +296,7 @@ static gl_list_t dblookup (MYDBM_FILE dbf, const char *page, bool matches = false; info = infoalloc (); - split_content (MYDBM_DPTR (cont), info); + split_content (dbf, MYDBM_DPTR (cont), info); if (!info->name) info->name = xstrdup (page); if (!(flags & MATCH_CASE) || STREQ (info->name, page)) { @@ -357,13 +357,13 @@ static gl_list_t dblookup (MYDBM_FILE dbf, const char *page, if (MYDBM_DPTR (multi_cont) == NULL) { error (0, 0, _("bad fetch on multi key %s"), MYDBM_DPTR (key)); - gripe_corrupt_data (); + gripe_corrupt_data (dbf); } MYDBM_FREE_DPTR (key); /* Allocate info struct and add it to the list. */ info = infoalloc (); - split_content (MYDBM_DPTR (multi_cont), info); + split_content (dbf, MYDBM_DPTR (multi_cont), info); if (!info->name) info->name = xstrdup (ref->name); gl_list_add_last (infos, info); @@ -427,7 +427,7 @@ gl_list_t dblookup_pattern (MYDBM_FILE dbf, const char *pattern, #else /* BTREE */ int end; - end = btree_nextkeydata (dbf, &key, &cont); + end = man_btree_nextkeydata (dbf, &key, &cont); while (!end) { #endif /* !BTREE */ struct mandata info; @@ -442,7 +442,7 @@ gl_list_t dblookup_pattern (MYDBM_FILE dbf, const char *pattern, error (FATAL, 0, _("Database %s corrupted; rebuild with " "mandb --create"), - database); + dbf->name); } if (*MYDBM_DPTR (key) == '$') @@ -453,7 +453,7 @@ gl_list_t dblookup_pattern (MYDBM_FILE dbf, const char *pattern, /* a real page */ - split_content (MYDBM_DPTR (cont), &info); + split_content (dbf, MYDBM_DPTR (cont), &info); /* If there's a section given, does it match either the * section or extension of this page? @@ -505,7 +505,7 @@ nextpage: #else /* BTREE */ MYDBM_FREE_DPTR (cont); MYDBM_FREE_DPTR (key); - end = btree_nextkeydata (dbf, &key, &cont); + end = man_btree_nextkeydata (dbf, &key, &cont); #endif /* !BTREE */ info.addr = NULL; free_mandata_elements (&info); diff --git a/libdb/db_ndbm.c b/libdb/db_ndbm.c index 992173ae..64000c1c 100644 --- a/libdb/db_ndbm.c +++ b/libdb/db_ndbm.c @@ -41,21 +41,28 @@ #include "manconfig.h" -#include "mydbm.h" #include "db_storage.h" +#include "db_xdbm.h" +#include "mydbm.h" /* release the lock and close the database */ -int ndbm_flclose (DBM *db) +static void raw_close (man_ndbm_wrapper wrap) +{ + flock (dbm_dirfno (wrap->file), LOCK_UN); + dbm_close (wrap->file); +} + +void man_ndbm_close (man_ndbm_wrapper wrap) { - flock (dbm_dirfno (db), LOCK_UN); - dbm_close (db); - return 0; + man_xdbm_close (wrap, raw_close); } /* open a ndbm type database, with file locking. */ -DBM* ndbm_flopen (char *filename, int flags, int mode) +man_ndbm_wrapper man_ndbm_open (const char *name, int flags, int mode) { - DBM *db; + man_ndbm_wrapper wrap; + char *name_copy; + DBM *file; int lock_op; int lock_failed; @@ -66,44 +73,76 @@ DBM* ndbm_flopen (char *filename, int flags, int mode) lock_op = LOCK_SH | LOCK_NB; } + /* At least GDBM's version of dbm_open declares the file name + * parameter as non-const. This is probably incorrect, but take a + * copy just in case. + */ + name_copy = xstrdup (name); + if (flags & O_TRUNC) { /* opening the db is destructive, need to lock first */ char *dir_fname; int dir_fd; - db = NULL; + file = NULL; lock_failed = 1; - dir_fname = xasprintf ("%s.dir", filename); + dir_fname = xasprintf ("%s.dir", name); dir_fd = open (dir_fname, flags & ~O_TRUNC, mode); free (dir_fname); if (dir_fd != -1) { if (!(lock_failed = flock (dir_fd, lock_op))) - db = dbm_open (filename, flags, mode); + file = dbm_open (name_copy, flags, mode); close (dir_fd); } } else { - db = dbm_open (filename, flags, mode); - if (db) - lock_failed = flock (dbm_dirfno (db), lock_op); + file = dbm_open (name_copy, flags, mode); + if (file) + lock_failed = flock (dbm_dirfno (file), lock_op); } - if (!db) + free (name_copy); + + if (!file) return NULL; if (lock_failed) { - gripe_lock (filename); - dbm_close (db); + gripe_lock (name); + dbm_close (file); return NULL; } - return db; + wrap = xmalloc (sizeof *wrap); + wrap->name = xstrdup (name); + wrap->file = file; + + return wrap; +} + +static datum unsorted_firstkey (man_ndbm_wrapper wrap) +{ + return copy_datum (dbm_firstkey (wrap->file)); +} + +static datum unsorted_nextkey (man_ndbm_wrapper wrap, datum key _GL_UNUSED) +{ + return copy_datum (dbm_nextkey (wrap->file)); +} + +datum man_ndbm_firstkey (man_ndbm_wrapper wrap) +{ + return man_xdbm_firstkey (wrap, unsorted_firstkey, unsorted_nextkey); +} + +datum man_ndbm_nextkey (man_ndbm_wrapper wrap, datum key) +{ + return man_xdbm_nextkey (wrap, key); } -struct timespec ndbm_get_time (DBM *db) +struct timespec man_ndbm_get_time (man_ndbm_wrapper wrap) { struct stat st; - if (fstat (dbm_dirfno (db), &st) < 0) { + if (fstat (dbm_dirfno (wrap->file), &st) < 0) { struct timespec t; t.tv_sec = -1; t.tv_nsec = -1; @@ -112,13 +151,13 @@ struct timespec ndbm_get_time (DBM *db) return get_stat_mtime (&st); } -void ndbm_set_time (DBM *db, const struct timespec time) +void man_ndbm_set_time (man_ndbm_wrapper wrap, const struct timespec time) { struct timespec times[2]; times[0] = time; times[1] = time; - futimens (dbm_dirfno (db), times); + futimens (dbm_dirfno (wrap->file), times); } #endif /* NDBM */ diff --git a/libdb/db_storage.h b/libdb/db_storage.h index a04196bc..c6d412f9 100644 --- a/libdb/db_storage.h +++ b/libdb/db_storage.h @@ -90,12 +90,13 @@ extern int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *in); extern void dbprintf (const struct mandata *info); extern void free_mandata_elements (struct mandata *pinfo); extern void free_mandata_struct (struct mandata *pinfo); -extern void split_content (char *cont_ptr, struct mandata *pinfo); +extern void split_content (MYDBM_FILE dbf, char *cont_ptr, + struct mandata *pinfo); extern int compare_ids (char a, char b, int promote_links); /* local to db routines */ -extern void gripe_lock (char *filename); -extern void gripe_corrupt_data (void); +extern void gripe_lock (const char *filename); +extern void gripe_corrupt_data (MYDBM_FILE dbf); extern datum make_multi_key (const char *page, const char *ext); /* allocate a mandata structure */ @@ -104,7 +105,7 @@ extern datum make_multi_key (const char *page, const char *ext); extern char *name_to_key (const char *name); /* Returns a list of struct name_ext. */ extern gl_list_t list_extensions (char *data); -extern void gripe_replace_key (const char *data); +extern void gripe_replace_key (MYDBM_FILE dbf, const char *data); extern const char *dash_if_unset (const char *str); #endif diff --git a/libdb/db_store.c b/libdb/db_store.c index 062db71f..508a41aa 100644 --- a/libdb/db_store.c +++ b/libdb/db_store.c @@ -33,9 +33,6 @@ #include "timespec.h" #include "xvasprintf.h" -#include "gettext.h" -#define _(String) gettext (String) - #include "manconfig.h" #include "error.h" @@ -52,7 +49,7 @@ * If promote_links is true, consider SO_MAN equivalent to ULT_MAN. This is * appropriate when sorting candidate pages for display. */ -int compare_ids (char a, char b, int promote_links) +int _GL_ATTRIBUTE_CONST compare_ids (char a, char b, int promote_links) { #ifdef FAVOUR_STRAYCATS if (a == WHATIS_MAN && b == STRAY_CAT) @@ -94,13 +91,13 @@ static int replace_if_necessary (MYDBM_FILE dbf, timespec_cmp (newdata->mtime, olddata->mtime) > 0) { debug ("replace_if_necessary(): newer mtime; replacing\n"); if (MYDBM_REPLACE (dbf, newkey, newcont)) - gripe_replace_key (MYDBM_DPTR (newkey)); + gripe_replace_key (dbf, MYDBM_DPTR (newkey)); return 0; } if (compare_ids (newdata->id, olddata->id, 0) < 0) { if (MYDBM_REPLACE (dbf, newkey, newcont)) - gripe_replace_key (MYDBM_DPTR (newkey)); + gripe_replace_key (dbf, MYDBM_DPTR (newkey)); return 0; } @@ -221,7 +218,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) in->name = xstrdup (base); oldcont = make_content (in); if (MYDBM_REPLACE (dbf, oldkey, oldcont)) - gripe_replace_key (MYDBM_DPTR (oldkey)); + gripe_replace_key (dbf, MYDBM_DPTR (oldkey)); MYDBM_FREE_DPTR (oldcont); free (in->name); in->name = NULL; @@ -243,7 +240,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) MYDBM_FREE_DPTR (oldcont); cont = MYDBM_FETCH (dbf, newkey); - split_content (MYDBM_DPTR (cont), &info); + split_content (dbf, MYDBM_DPTR (cont), &info); ret = replace_if_necessary (dbf, in, &info, newkey, newcont); /* MYDBM_FREE_DPTR (cont); */ @@ -270,7 +267,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) /* Try to replace the old simple data with the new stuff */ if (MYDBM_REPLACE (dbf, oldkey, newcont)) - gripe_replace_key (MYDBM_DPTR (oldkey)); + gripe_replace_key (dbf, MYDBM_DPTR (oldkey)); MYDBM_FREE_DPTR (newcont); } else { /* situation (3) */ @@ -285,7 +282,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) /* Extract the old singular reference */ - split_content (MYDBM_DPTR (oldcont), &old); + split_content (dbf, MYDBM_DPTR (oldcont), &old); /* Create multi keys for both old and new items, create new content */ @@ -336,7 +333,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) * certainly better. */ if (MYDBM_REPLACE (dbf, lastkey, lastcont)) - gripe_replace_key (MYDBM_DPTR (lastkey)); + gripe_replace_key (dbf, MYDBM_DPTR (lastkey)); MYDBM_FREE_DPTR (lastkey); MYDBM_FREE_DPTR (lastcont); @@ -345,7 +342,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) newcont = make_content (in); if (MYDBM_REPLACE (dbf, newkey, newcont)) - gripe_replace_key (MYDBM_DPTR (newkey)); + gripe_replace_key (dbf, MYDBM_DPTR (newkey)); MYDBM_FREE_DPTR (newkey); MYDBM_FREE_DPTR (newcont); @@ -356,7 +353,7 @@ int dbstore (MYDBM_FILE dbf, struct mandata *in, const char *base) "\t%s\t%s\t%s\t%s", old_name, old.ext, base, in->ext)); if (MYDBM_REPLACE (dbf, oldkey, newcont)) - gripe_replace_key (MYDBM_DPTR (oldkey)); + gripe_replace_key (dbf, MYDBM_DPTR (oldkey)); /* MYDBM_FREE_DPTR (oldcont); */ free_mandata_elements (&old); diff --git a/libdb/db_ver.c b/libdb/db_ver.c index 5ac306d2..56b73392 100644 --- a/libdb/db_ver.c +++ b/libdb/db_ver.c @@ -50,11 +50,12 @@ int dbver_rd (MYDBM_FILE dbfile) MYDBM_FREE_DPTR (key); if (MYDBM_DPTR (content) == NULL) { - debug (_("warning: %s has no version identifier\n"), database); + debug (_("warning: %s has no version identifier\n"), + dbfile->name); return 1; } else if (!STREQ (MYDBM_DPTR (content), VER_ID)) { debug (_("warning: %s is version %s, expecting %s\n"), - database, MYDBM_DPTR (content), VER_ID); + dbfile->name, MYDBM_DPTR (content), VER_ID); MYDBM_FREE_DPTR (content); return 1; } else { @@ -76,7 +77,7 @@ void dbver_wr (MYDBM_FILE dbfile) if (MYDBM_INSERT (dbfile, key, content) != 0) error (FATAL, 0, _("fatal: unable to insert version identifier into %s"), - database); + dbfile->name); MYDBM_FREE_DPTR (key); MYDBM_FREE_DPTR (content); diff --git a/libdb/db_xdbm.c b/libdb/db_xdbm.c new file mode 100644 index 00000000..f0a9932e --- /dev/null +++ b/libdb/db_xdbm.c @@ -0,0 +1,169 @@ +/* + * db_xdbm.c: common code for gdbm and ndbm backends + * + * Copyright (C) 2003-2019 Colin Watson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if defined(GDBM) || defined(NDBM) + +#include <stdbool.h> +#include <string.h> +#include <stdlib.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 "manconfig.h" + +#include "cleanup.h" +#include "glcontainers.h" + +#include "db_xdbm.h" +#include "mydbm.h" + +static gl_map_t parent_keys; + +static int datum_compare (const void *a, const void *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)) + return 1; + else if (!MYDBM_DPTR (*right)) + return -1; + + if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right)) + minsize = MYDBM_DSIZE (*left); + else + minsize = MYDBM_DSIZE (*right); + cmp = strncmp (MYDBM_DPTR (*left), MYDBM_DPTR (*right), minsize); + if (cmp) + return cmp; + else if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right)) + return 1; + 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 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_xdbm_firstkey (MYDBM_FILE dbf, + man_xdbm_unsorted_firstkey unsorted_firstkey, + man_xdbm_unsorted_nextkey unsorted_nextkey) +{ + 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 = unsorted_firstkey (dbf); + while (MYDBM_DPTR (*key)) { + datum *next; + + gl_sortedlist_add (keys, datum_compare, key); + next = XMALLOC (datum); + *next = unsorted_nextkey (dbf, *key); + key = next; + } + + 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. */ + gl_map_put (parent_keys, xstrdup (dbf->name), keys); + + if (gl_list_size (keys)) + return copy_datum (*(datum *) gl_list_get_at (keys, 0)); + else + return empty_datum; +} + +datum man_xdbm_nextkey (MYDBM_FILE dbf, datum key) +{ + gl_list_t keys; + gl_list_node_t node, next_node; + + if (!parent_keys) + return empty_datum; + keys = (gl_list_t) gl_map_get (parent_keys, dbf->name); + if (!keys) + return empty_datum; + + 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 (*(datum *) gl_list_node_value (keys, next_node)); +} + +void man_xdbm_close (MYDBM_FILE dbf, man_xdbm_raw_close raw_close) +{ + if (!dbf) + return; + + if (parent_keys) + gl_map_remove (parent_keys, dbf->name); + + free (dbf->name); + raw_close (dbf); + free (dbf); +} + +#endif /* GDBM || NDBM */ diff --git a/libdb/db_xdbm.h b/libdb/db_xdbm.h new file mode 100644 index 00000000..9d7f4bf7 --- /dev/null +++ b/libdb/db_xdbm.h @@ -0,0 +1,40 @@ +/* + * db_xdbm.c: interface to common code for gdbm and ndbm backends + * + * Copyright (C) 2019 Colin Watson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAN_XDBM_H +#define MAN_XDBM_H + +#if defined(GDBM) || defined(NDBM) + +#include "mydbm.h" + +typedef datum (*man_xdbm_unsorted_firstkey) (MYDBM_FILE dbf); +typedef datum (*man_xdbm_unsorted_nextkey) (MYDBM_FILE dbf, datum key); +typedef void (*man_xdbm_raw_close) (MYDBM_FILE dbf); + +datum man_xdbm_firstkey (MYDBM_FILE dbf, + man_xdbm_unsorted_firstkey firstkey, + man_xdbm_unsorted_nextkey nextkey); +datum man_xdbm_nextkey (MYDBM_FILE dbf, datum key); +void man_xdbm_close (MYDBM_FILE dbf, man_xdbm_raw_close raw_close); + +#endif /* GDBM || NDBM */ + +#endif /* MAN_XDBM_H */ diff --git a/libdb/mydbm.h b/libdb/mydbm.h index 32053e3e..31f1d756 100644 --- a/libdb/mydbm.h +++ b/libdb/mydbm.h @@ -98,30 +98,37 @@ void man_gdbm_close (man_gdbm_wrapper wrap); # define BERKELEY_DB # endif /* _DB_H_ */ -extern DBM *ndbm_flopen(char *file, int flags, int mode); -extern struct timespec ndbm_get_time(DBM *db); -extern void ndbm_set_time(DBM *db, const struct timespec time); -extern int ndbm_flclose(DBM *db); +typedef struct { + char *name; + DBM *file; +} *man_ndbm_wrapper; + +extern man_ndbm_wrapper man_ndbm_open (const char *name, int flags, int mode); +extern datum man_ndbm_firstkey (man_ndbm_wrapper wrap); +extern datum man_ndbm_nextkey (man_ndbm_wrapper wrap, datum key); +extern struct timespec man_ndbm_get_time (man_ndbm_wrapper wrap); +extern void man_ndbm_set_time (man_ndbm_wrapper wrap, const struct timespec time); +extern void man_ndbm_close (man_ndbm_wrapper wrap); # define DB_EXT "" -# define MYDBM_FILE DBM* +# define MYDBM_FILE man_ndbm_wrapper # define MYDBM_DPTR(d) ((d).dptr) # define MYDBM_SET_DPTR(d, value) ((d).dptr = (value)) # define MYDBM_DSIZE(d) ((d).dsize) -# define MYDBM_CTRWOPEN(file) ndbm_flopen(file, O_TRUNC|O_CREAT|O_RDWR, DBMODE) -# define MYDBM_CRWOPEN(file) ndbm_flopen(file, O_CREAT|O_RDWR, DBMODE) -# define MYDBM_RWOPEN(file) ndbm_flopen(file, O_RDWR, DBMODE) -# define MYDBM_RDOPEN(file) ndbm_flopen(file, O_RDONLY, DBMODE) -# define MYDBM_INSERT(db, key, cont) dbm_store(db, key, cont, DBM_INSERT) -# define MYDBM_REPLACE(db, key, cont) dbm_store(db, key, cont, DBM_REPLACE) -# define MYDBM_EXISTS(db, key) (dbm_fetch(db, key).dptr != NULL) -# define MYDBM_DELETE(db, key) dbm_delete(db, key) -# define MYDBM_FETCH(db, key) copy_datum(dbm_fetch(db, key)) -# define MYDBM_CLOSE(db) ndbm_flclose(db) -# define MYDBM_FIRSTKEY(db) copy_datum(dbm_firstkey(db)) -# define MYDBM_NEXTKEY(db, key) copy_datum(dbm_nextkey(db)) -# define MYDBM_GET_TIME(db) ndbm_get_time(db) -# define MYDBM_SET_TIME(db, time) ndbm_set_time(db, time) +# define MYDBM_CTRWOPEN(file) man_ndbm_open(file, O_TRUNC|O_CREAT|O_RDWR, DBMODE) +# define MYDBM_CRWOPEN(file) man_ndbm_open(file, O_CREAT|O_RDWR, DBMODE) +# define MYDBM_RWOPEN(file) man_ndbm_open(file, O_RDWR, DBMODE) +# define MYDBM_RDOPEN(file) man_ndbm_open(file, O_RDONLY, DBMODE) +# define MYDBM_INSERT(db, key, cont) dbm_store((db)->file, key, cont, DBM_INSERT) +# define MYDBM_REPLACE(db, key, cont) dbm_store((db)->file, key, cont, DBM_REPLACE) +# define MYDBM_EXISTS(db, key) (dbm_fetch((db)->file, key).dptr != NULL) +# define MYDBM_DELETE(db, key) dbm_delete((db)->file, key) +# define MYDBM_FETCH(db, key) copy_datum(dbm_fetch((db)->file, key)) +# define MYDBM_CLOSE(db) man_ndbm_close(db) +# define MYDBM_FIRSTKEY(db) man_ndbm_firstkey(db) +# define MYDBM_NEXTKEY(db, key) man_ndbm_nextkey(db, key) +# define MYDBM_GET_TIME(db) man_ndbm_get_time(db) +# define MYDBM_SET_TIME(db, time) man_ndbm_set_time(db, time) # define MYDBM_REORG(db) /* nothing - not implemented */ # elif defined(BTREE) && !defined(NDBM) && !defined(GDBM) @@ -131,39 +138,48 @@ extern int ndbm_flclose(DBM *db); # include <limits.h> # include BDB_H +typedef struct { + char *name; + DB *file; +} *man_btree_wrapper; + typedef DBT datum; -extern DB *btree_flopen(char *filename, int flags, int mode); -extern int btree_close(DB *db); -extern int btree_exists(DB *db, datum key); -extern datum btree_fetch(DB *db, datum key); -extern int btree_insert(DB *db, datum key, datum cont); -extern datum btree_firstkey(DB *db); -extern datum btree_nextkey(DB *db); -extern int btree_replace(DB *db, datum key, datum content); -extern int btree_nextkeydata(DB *db, datum *key, datum *cont); -extern struct timespec btree_get_time(DB *db); -extern void btree_set_time(DB *db, const struct timespec time); +extern man_btree_wrapper man_btree_open (const char *filename, int flags, + int mode); +extern void man_btree_close (man_btree_wrapper wrap); +extern int man_btree_exists (man_btree_wrapper wrap, datum key); +extern datum man_btree_fetch (man_btree_wrapper wrap, datum key); +extern int man_btree_insert (man_btree_wrapper wrap, datum key, datum cont); +extern datum man_btree_firstkey (man_btree_wrapper wrap); +extern datum man_btree_nextkey (man_btree_wrapper wrap); +extern int man_btree_replace (man_btree_wrapper wrap, + datum key, datum content); +extern int man_btree_nextkeydata (man_btree_wrapper wrap, + datum *key, datum *cont); +extern struct timespec man_btree_get_time (man_btree_wrapper wrap); +extern void man_btree_set_time (man_btree_wrapper wrap, + const struct timespec time); # define DB_EXT ".bt" -# define MYDBM_FILE DB* +# define MYDBM_FILE man_btree_wrapper # define MYDBM_DPTR(d) ((char *) (d).data) # define MYDBM_SET_DPTR(d, value) ((d).data = (char *) (value)) # define MYDBM_DSIZE(d) ((d).size) -# define MYDBM_CTRWOPEN(file) btree_flopen(file, O_TRUNC|O_CREAT|O_RDWR, DBMODE) -# define MYDBM_CRWOPEN(file) btree_flopen(file, O_CREAT|O_RDWR, DBMODE) -# define MYDBM_RWOPEN(file) btree_flopen(file, O_RDWR, DBMODE) -# define MYDBM_RDOPEN(file) btree_flopen(file, O_RDONLY, DBMODE) -# define MYDBM_INSERT(db, key, cont) btree_insert(db, key, cont) -# define MYDBM_REPLACE(db, key, cont) btree_replace(db, key, cont) -# define MYDBM_EXISTS(db, key) btree_exists(db, key) -# define MYDBM_DELETE(db, key) ((db->del)(db, &key, 0) ? -1 : 0) -# define MYDBM_FETCH(db, key) btree_fetch(db, key) -# define MYDBM_CLOSE(db) btree_close(db) -# define MYDBM_FIRSTKEY(db) btree_firstkey(db) -# define MYDBM_NEXTKEY(db, key) btree_nextkey(db) -# define MYDBM_GET_TIME(db) btree_get_time(db) -# define MYDBM_SET_TIME(db, time) btree_set_time(db, time) +# define MYDBM_CTRWOPEN(file) man_btree_open(file, O_TRUNC|O_CREAT|O_RDWR, DBMODE) +# define MYDBM_CRWOPEN(file) man_btree_open(file, O_CREAT|O_RDWR, DBMODE) +# define MYDBM_RWOPEN(file) man_btree_open(file, O_RDWR, DBMODE) +# define MYDBM_RDOPEN(file) man_btree_open(file, O_RDONLY, DBMODE) +# define MYDBM_INSERT(db, key, cont) man_btree_insert(db, key, cont) +# define MYDBM_REPLACE(db, key, cont) man_btree_replace(db, key, cont) +# define MYDBM_EXISTS(db, key) man_btree_exists(db, key) +# define MYDBM_DELETE(db, key) (((db)->file->del)((db)->file, &key, 0) ? -1 : 0) +# define MYDBM_FETCH(db, key) man_btree_fetch(db, key) +# define MYDBM_CLOSE(db) man_btree_close(db) +# define MYDBM_FIRSTKEY(db) man_btree_firstkey(db) +# define MYDBM_NEXTKEY(db, key) man_btree_nextkey(db) +# define MYDBM_GET_TIME(db) man_btree_get_time(db) +# define MYDBM_SET_TIME(db, time) man_btree_set_time(db, time) # define MYDBM_REORG(db) /* nothing - not implemented */ # else /* not GDBM or NDBM or BTREE */ @@ -174,8 +190,6 @@ extern void btree_set_time(DB *db, const struct timespec time); #define MYDBM_SET(d, value) do { MYDBM_SET_DPTR(d, value); MYDBM_RESET_DSIZE(d); } while (0) #define MYDBM_FREE_DPTR(d) do { free (MYDBM_DPTR (d)); MYDBM_SET_DPTR (d, NULL); } while (0) -extern char *database; - /* db_lookup.c */ extern datum copy_datum (datum dat); |