From 85f1e72da83e3078e2ae1f78093ef0966e43cec1 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 19 Jul 2016 12:01:48 +0300 Subject: Implement gdbm_recover function * configure.ac: Don't check for rename. * src/Makefile.am (libgdbm_la_SOURCES): Add recover.c * src/recover.c: New file. * src/bucket.c (_gdbm_get_bucket): Remove extra space before [ * src/err.c (prerror): Take additional argument (gdbm_perror): Print system errno if necessary. * src/gdbm.h.in (GDBM_CLOERROR): New flag. (gdbm_fd_open, gdbm_copy_meta): New proto. (gdbm_last_syserr,gdbm_db_strerror,gdbm_recover): New proto. (gdbm_syserr): New extern. (gdbm_recovery): New struct. (GDBM_RCVR_DEFAULT,GDBM_RCVR_ERRFUN) (GDBM_RCVR_MAX_FAILED_KEYS) (GDBM_RCVR_MAX_FAILED_BUCKETS) (GDBM_RCVR_MAX_FAILURES) (GDBM_RCVR_BACKUP): New flags. (GDBM_BACKUP_FAILED): New error code. * src/gdbmclose.c (gdbm_close): Work correctly if dbf->desc == -1. * src/gdbmcount.c (gdbm_count): Remove spurious sorting. Use _gdbm_next_bucket_dir for iterating over the buckets. * src/gdbmdefs.h (struct gdbm_file_info) : New members. * src/gdbmerrno.c (gdbm_set_errno): Set last_syserror as well. (gdbm_clear_error): Reset last_syserror. (gdbm_last_syserr): New function. (gdbm_errlist): New entry for GDBM_BACKUP_FAILED. (gdbm_db_strerror): New function. (gdbm_syserr): New global. * src/gdbmload.c (get_parms): Buffer can be NULL. * src/gdbmopen.c (gdbm_fd_open): New function. (gdbm_open): Rewrite as a wrapper over gdbm_fd_open. * src/gdbmreorg.c (gdbm_reorganize): Rewrite as a wrapper over gdbm_recover. * src/proto.h (_gdbm_next_bucket_dir): New proto. * src/gdbmtool.c: New command: recover. * tests/.gitignore: Add gtrecover * tests/gtrecover.c: New test program. * tests/Makefile.am: Build gtrecover --- tests/.gitignore | 1 + tests/Makefile.am | 2 + tests/gtrecover.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 tests/gtrecover.c (limited to 'tests') diff --git a/tests/.gitignore b/tests/.gitignore index 0883563..a339f8d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -18,6 +18,7 @@ gtdump gtfetch gtload gtopt +gtrecover gtver num2word package.m4 diff --git a/tests/Makefile.am b/tests/Makefile.am index f706213..a95db7e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -113,6 +113,7 @@ check_PROGRAMS = \ gtfetch\ gtload\ gtopt\ + gtrecover\ gtver\ num2word\ $(DBMPROGS) @@ -125,6 +126,7 @@ gtdump_LDADD = ../src/libgdbm.la gtfetch_LDADD = ../src/libgdbm.la gtver_LDADD = ../src/libgdbm.la gtopt_LDADD = ../src/libgdbm.la +gtrecover_LDADD = ../src/libgdbm.la g_open_ce_LDADD = ../src/libgdbm.la g_reorg_ce_LDADD = ../src/libgdbm.la diff --git a/tests/gtrecover.c b/tests/gtrecover.c new file mode 100644 index 0000000..7bb1f1e --- /dev/null +++ b/tests/gtrecover.c @@ -0,0 +1,124 @@ +/* This file is part of GDBM test suite. + Copyright (C) 2016 Free Software Foundation, Inc. + + GDBM is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GDBM 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GDBM. If not, see . +*/ +#include "autoconf.h" +#include +#include +#include +#include +#include "gdbm.h" +#include "progname.h" +#include + +const char *progname; + +void +err_printer (void *data, char const *fmt, ...) +{ + va_list ap; + + fprintf (stderr, "%s: ", progname); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fprintf (stderr, "\n"); +} + +int +main (int argc, char **argv) +{ + const char *dbname; + GDBM_FILE dbf; + int rc = 0; + int open_flags = GDBM_WRITER; + gdbm_recovery rcvr; + int rcvr_flags = 0; + char *p; + + progname = canonical_progname (argv[0]); + while (--argc) + { + char *arg = *++argv; + + if (strcmp (arg, "-h") == 0) + { + printf ("usage: %s [-nolock] [-nommap] [-verbose] [-backup] [-max-failures=N] [-max-failed-keys=N] [-max-failed-buckets=N] DBFILE\n", + progname); + exit (0); + } + else if (strcmp (arg, "-nolock") == 0) + open_flags |= GDBM_NOLOCK; + else if (strcmp (arg, "-nommap") == 0) + open_flags |= GDBM_NOMMAP; + else if (strcmp (arg, "-verbose") == 0) + { + rcvr.errfun = err_printer; + rcvr_flags |= GDBM_RCVR_ERRFUN; + } + else if (strcmp (arg, "-backup") == 0) + rcvr_flags |= GDBM_RCVR_BACKUP; + else if (strncmp (arg, "-max-failures=", 14) == 0) + { + rcvr.max_failures = strtoul (arg + 14, &p, 10); + assert (*p == 0); + rcvr_flags |= GDBM_RCVR_MAX_FAILURES; + } + else if (strncmp (arg, "-max-failed-keys=", 17) == 0) + { + rcvr.max_failed_keys = strtoul (arg + 17, &p, 10); + assert (*p == 0); + rcvr_flags |= GDBM_RCVR_MAX_FAILED_KEYS; + } + else if (strncmp (arg, "-max-failed-buckets=", 20) == 0) + { + rcvr.max_failures = strtoul (arg + 20, &p, 10); + assert (*p == 0); + rcvr_flags |= GDBM_RCVR_MAX_FAILED_BUCKETS; + } + else if (strcmp (arg, "--") == 0) + { + --argc; + ++argv; + break; + } + else if (arg[0] == '-') + { + fprintf (stderr, "%s: unknown option %s\n", progname, arg); + exit (1); + } + else + break; + } + + if (argc < 1) + { + fprintf (stderr, "%s: wrong arguments\n", progname); + exit (1); + } + dbname = *argv; + + dbf = gdbm_open (dbname, 0, open_flags, 0, NULL); + if (!dbf) + { + fprintf (stderr, "gdbm_open failed: %s\n", gdbm_strerror (gdbm_errno)); + exit (1); + } + + rc = gdbm_recover (dbf, &rcvr, rcvr_flags); + + gdbm_close (dbf); + exit (rc); +} -- cgit v1.2.1