diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-10-18 17:23:07 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-10-18 17:23:07 +0300 |
commit | 852ff1b6e81ce13fdcd1fd4fb272b17d760760b3 (patch) | |
tree | 3113d09e84353d47dfd48b237c8b5e2c62eed869 | |
parent | 2ff4ae9c745d4b9e6ee36468c81554027f66c35b (diff) | |
download | gdbm-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.c | 31 | ||||
-rw-r--r-- | src/gdbmtool.c | 2 | ||||
-rw-r--r-- | src/proto.h | 2 | ||||
-rw-r--r-- | src/recover.c | 2 |
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; |