diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-24 11:35:24 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-24 11:35:24 +0300 |
commit | 371bb85fe378ffd0ed6ddc81985d450cef5835a3 (patch) | |
tree | 6ab2d142b7aa1f9b29ec50b891c8293774964209 /src/recover.c | |
parent | f82d0b213fd2cdce80dc891906fba8d589115664 (diff) | |
download | gdbm-371bb85fe378ffd0ed6ddc81985d450cef5835a3.tar.gz gdbm-371bb85fe378ffd0ed6ddc81985d450cef5835a3.tar.bz2 |
More error checking; improve gdbm_recover
* Makefile.am (set-dist-date): New rule
(dist-hook): Catch FIXMEs in NEWS.
* NEWS: Updated.
* src/findkey.c (gdbm_bucket_element_valid_p): New function.
(_gdbm_read_entry): Validate the retrieved bucket element.
* src/gdbm.h.in (gdbm_recovery): New member: duplicate_keys.
(GDBM_BAD_HASH_TABLE): New error code.
* src/gdbmdefs.h (TYPE_WIDTH,SIGNED_TYPE_MAXIMUM)
(OFF_T_MAX): New defines.
(off_t_sum_ok): New function.
(gdbm_bucket_element_valid_p): New prototype.
* src/gdbmerrno.c: Support for GDBM_BAD_HASH_TABLE code.
* src/gdbmtool.c (recover_handler): Fix argument counting.
New argument 'summary' prints statistics summary at the end
of the run.
(export_handler,import_handler): Fix argument counting.
* src/mmap.c (SUM_FILE_SIZE): Rewrite as inlined function.
Add error checking.
(_gdbm_mapped_remap): More error checking.
* src/recover.c (run_recovery): Don't bail out on GDBM_CANNOT_REPLACE.
(gdbm_recover): Initialize duplicate_keys
* src/systems.h: Include limits.h
Diffstat (limited to 'src/recover.c')
-rw-r--r-- | src/recover.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/recover.c b/src/recover.c index d6d4ff9..721c23f 100644 --- a/src/recover.c +++ b/src/recover.c @@ -303,37 +303,52 @@ run_recovery (GDBM_FILE dbf, GDBM_FILE new_dbf, gdbm_recovery *rcvr, int flags) return -1; continue; } key.dptr = dptr; key.dsize = dbf->bucket->h_table[i].key_size; data.dptr = dptr + key.dsize; data.dsize = dbf->bucket->h_table[i].data_size; if (gdbm_store (new_dbf, key, data, GDBM_INSERT) != 0) { + switch (gdbm_last_errno (new_dbf)) + { + case GDBM_CANNOT_REPLACE: + rcvr->duplicate_keys++; + if (flags & GDBM_RCVR_ERRFUN) + rcvr->errfun (rcvr->data, + _("ignoring duplicate key %d:%d (%lu:%d)"), + bucket_dir, i, + (unsigned long) dbf->bucket->h_table[i].data_pointer, + dbf->bucket->h_table[i].key_size + + dbf->bucket->h_table[i].data_size); + break; + + default: if (flags & GDBM_RCVR_ERRFUN) rcvr->errfun (rcvr->data, _("fatal: can't store element %d:%d (%lu:%d): %s"), bucket_dir, i, (unsigned long) dbf->bucket->h_table[i].data_pointer, dbf->bucket->h_table[i].key_size + dbf->bucket->h_table[i].data_size, gdbm_db_strerror (new_dbf)); return -1; } } } } + } return 0; } int gdbm_recover (GDBM_FILE dbf, gdbm_recovery *rcvr, int flags) { GDBM_FILE new_dbf; /* The new file. */ char *new_name; /* A temporary name. */ size_t len; int fd; int rc; @@ -347,24 +362,25 @@ gdbm_recover (GDBM_FILE dbf, gdbm_recovery *rcvr, int flags) } /* Initialize gdbm_recovery structure */ if (!rcvr) { rcvr = &rs; flags = 0; } rcvr->recovered_keys = 0; rcvr->recovered_buckets = 0; rcvr->failed_keys = 0; rcvr->failed_buckets = 0; + rcvr->duplicate_keys = 0; rcvr->backup_name = NULL; rc = 0; if ((flags & GDBM_RCVR_FORCE) || check_db (dbf)) { len = strlen (dbf->name); new_name = malloc (len + sizeof (TMPSUF)); if (!new_name) { GDBM_SET_ERRNO (NULL, GDBM_MALLOC_ERROR, FALSE); return -1; } |