diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gdbmopen.c | 55 | ||||
-rw-r--r-- | src/gdbmtool.c | 2 | ||||
-rw-r--r-- | src/proto.h | 2 | ||||
-rw-r--r-- | src/recover.c | 4 |
4 files changed, 43 insertions, 20 deletions
diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 7ec57e7..fe2527e 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -136,6 +136,7 @@ static int validate_header (gdbm_file_header const *hdr, struct stat const *st) { int dir_size, dir_bits; + int result = GDBM_NO_ERROR; /* Is the magic number good? */ if (hdr->header_magic != GDBM_MAGIC) @@ -169,8 +170,7 @@ 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; /* Make sure dir and dir + dir_size fall within the file boundary */ if (!(hdr->dir > 0 @@ -196,9 +196,20 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) != hdr->avail.size) return GDBM_BAD_HEADER; - 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); +} + /* Do we have ftruncate? */ static inline int _gdbm_ftruncate (GDBM_FILE dbf) @@ -261,7 +272,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->mapped_size = 0; dbf->mapped_pos = 0; dbf->mapped_off = 0; - + /* Save name of file. */ dbf->name = strdup (file_name); if (dbf->name == NULL) @@ -521,7 +532,11 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, /* Is the header valid? */ 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) { if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; @@ -627,7 +642,8 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->bucket_changed = FALSE; dbf->second_changed = FALSE; - 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"); /* Everything is fine, return the pointer to the file information structure. */ @@ -664,20 +680,23 @@ gdbm_open (const char *file, int block_size, int flags, int mode, switch (flags & GDBM_OPENMASK) { - case GDBM_READER: - fbits = O_RDONLY; - break; + case GDBM_READER: + fbits = O_RDONLY; + break; - case GDBM_WRITER: - fbits = O_RDWR; - break; + case GDBM_WRITER: + fbits = O_RDWR; + break; - case GDBM_NEWDB: - fbits = O_RDWR|O_CREAT; - break; + case GDBM_WRCREAT: + case GDBM_NEWDB: + fbits = O_RDWR|O_CREAT; + break; - default: - fbits = O_RDWR|O_CREAT; + default: + errno = EINVAL; + GDBM_SET_ERRNO2 (NULL, GDBM_FILE_OPEN_ERROR, FALSE, GDBM_DEBUG_OPEN); + return NULL; } if (flags & GDBM_CLOEXEC) fbits |= O_CLOEXEC; diff --git a/src/gdbmtool.c b/src/gdbmtool.c index 8c97e1e..bbadbae 100644 --- a/src/gdbmtool.c +++ b/src/gdbmtool.c @@ -969,7 +969,7 @@ export_handler (struct handler_param *param) int i; int filemode; - for (i = 0; i < param->argc; i++) + for (i = 1; i < param->argc; i++) { if (strcmp (PARAM_STRING (param, i), "truncate") == 0) flags = GDBM_NEWDB; diff --git a/src/proto.h b/src/proto.h index 02f6f9b..e3b6a45 100644 --- a/src/proto.h +++ b/src/proto.h @@ -53,6 +53,8 @@ void _gdbm_cache_entry_invalidate (GDBM_FILE, int); int gdbm_avail_block_validate (GDBM_FILE dbf, avail_block *avblk); int gdbm_bucket_avail_table_validate (GDBM_FILE dbf, hash_bucket *bucket); +int _gdbm_validate_header (GDBM_FILE dbf); + /* From mmap.c */ int _gdbm_mapped_init (GDBM_FILE); void _gdbm_mapped_unmap (GDBM_FILE); diff --git a/src/recover.c b/src/recover.c index a64a1b4..7cc20a2 100644 --- a/src/recover.c +++ b/src/recover.c @@ -206,6 +206,8 @@ check_db (GDBM_FILE dbf) int bucket_dir, i; int nbuckets = GDBM_DIR_COUNT (dbf); + if (_gdbm_validate_header (dbf)) + return 1; for (bucket_dir = 0; bucket_dir < nbuckets; bucket_dir = _gdbm_next_bucket_dir (dbf, bucket_dir)) { @@ -410,7 +412,7 @@ gdbm_recover (GDBM_FILE dbf, gdbm_recovery *rcvr, int flags) } rc = run_recovery (dbf, new_dbf, rcvr, flags); - + if (rc == 0) rc = _gdbm_finish_transfer (dbf, new_dbf, rcvr, flags); else |