aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-10-18 17:23:07 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-10-18 17:23:07 +0300
commit852ff1b6e81ce13fdcd1fd4fb272b17d760760b3 (patch)
tree3113d09e84353d47dfd48b237c8b5e2c62eed869
parent2ff4ae9c745d4b9e6ee36468c81554027f66c35b (diff)
downloadgdbm-852ff1b6e81ce13fdcd1fd4fb272b17d760760b3.tar.gz
gdbm-852ff1b6e81ce13fdcd1fd4fb272b17d760760b3.tar.bz2
Attempt recovery in case of invalid next_block header field
* src/gdbmopen.c (validate_header): Return GDBM_NEED_RECOVERY if next_block is invalid. (_gdbm_validate_header): New function. (gdbm_fd_open): Set need_recovery depending on return from validate_header. (gdbm_open): Bail out on invalid value of GDBM_OPENMASK bits. * src/proto.h (_gdbm_validate_header): New proto. * src/recover.c (check_db): Re-validate the header. * src/gdbmtool.c (export_handler): Fix option processing.
-rw-r--r--src/gdbmopen.c31
-rw-r--r--src/gdbmtool.c2
-rw-r--r--src/proto.h2
-rw-r--r--src/recover.c2
4 files changed, 30 insertions, 7 deletions
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 7ec57e7..fe2527e 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -138,2 +138,3 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
int dir_size, dir_bits;
+ int result = GDBM_NO_ERROR;
@@ -171,4 +172,3 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
if (hdr->next_block != st->st_size)
- /* FIXME: Should return GDBM_NEED_RECOVERY instead? */
- return GDBM_BAD_HEADER;
+ result = GDBM_NEED_RECOVERY;
@@ -198,3 +198,14 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
- return 0;
+ return result;
+}
+
+int
+_gdbm_validate_header (GDBM_FILE dbf)
+{
+ struct stat file_stat;
+
+ if (fstat (dbf->desc, &file_stat))
+ return GDBM_FILE_STAT_ERROR;
+
+ return validate_header (dbf->header, &file_stat);
}
@@ -523,3 +534,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
rc = validate_header (&partial_header, &file_stat);
- if (rc != GDBM_NO_ERROR)
+ if (rc == GDBM_NEED_RECOVERY)
+ {
+ dbf->need_recovery = 1;
+ }
+ else if (rc != GDBM_NO_ERROR)
{
@@ -629,3 +644,4 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
- GDBM_DEBUG (GDBM_DEBUG_ALL, "%s: opened successfully", dbf->name);
+ GDBM_DEBUG (GDBM_DEBUG_ALL, "%s: opened %s", dbf->name,
+ dbf->need_recovery ? "for recovery" : "successfully");
@@ -674,2 +690,3 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
+ case GDBM_WRCREAT:
case GDBM_NEWDB:
@@ -679,3 +696,5 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
default:
- fbits = O_RDWR|O_CREAT;
+ errno = EINVAL;
+ GDBM_SET_ERRNO2 (NULL, GDBM_FILE_OPEN_ERROR, FALSE, GDBM_DEBUG_OPEN);
+ return NULL;
}
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 8c97e1e..bbadbae 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -971,3 +971,3 @@ export_handler (struct handler_param *param)
- for (i = 0; i < param->argc; i++)
+ for (i = 1; i < param->argc; i++)
{
diff --git a/src/proto.h b/src/proto.h
index 02f6f9b..e3b6a45 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -55,2 +55,4 @@ int gdbm_bucket_avail_table_validate (GDBM_FILE dbf, hash_bucket *bucket);
+int _gdbm_validate_header (GDBM_FILE dbf);
+
/* From mmap.c */
diff --git a/src/recover.c b/src/recover.c
index a64a1b4..7cc20a2 100644
--- a/src/recover.c
+++ b/src/recover.c
@@ -208,2 +208,4 @@ check_db (GDBM_FILE dbf)
+ if (_gdbm_validate_header (dbf))
+ return 1;
for (bucket_dir = 0; bucket_dir < nbuckets;

Return to:

Send suggestions and report system problems to the System administrator.