diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-07-09 11:40:19 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-07-09 12:11:20 +0300 |
commit | e8cad816f36b1cad11bb67c96f0ce878cf30844e (patch) | |
tree | c971d9de6369f9e340a3764d848c24d4a2ce96e8 | |
parent | 0eafbb93c82a489204f54259593f2aaeb9cdbfc4 (diff) | |
download | gdbm-e8cad816f36b1cad11bb67c96f0ce878cf30844e.tar.gz gdbm-e8cad816f36b1cad11bb67c96f0ce878cf30844e.tar.bz2 |
Don't bail out on fatal errors, unless the user defines the fatal_err function
* src/bucket.c (_gdbm_get_bucket)
(_gdbm_split_bucket, _gdbm_write_bucket): Return error code. All callers
updated.
* src/proto.h (_gdbm_get_bucket)
(_gdbm_split_bucket, _gdbm_write_bucket): Update declarations
* src/falloc.c (push_avail_block)
(pop_avail_block): Return error code. All callers
updated.
* src/update.c (_gdbm_fatal): Exit only if the user defined
fatal_err function.
* src/gdbmerrno.c (gdbm_needs_recovery): New function.
* src/gdbm.h.in (gdbm_needs_recovery): New proto.
* compat/dbminit.c: Set gdbm_errno on fatal errors.
* compat/dbmopen.c: Likewise.
* src/findkey.c: Likewise.
* src/gdbm_load.c: Likewise.
* src/gdbmcount.c: Likewise.
* src/gdbmdefs.h: Likewise.
* src/gdbmdelete.c: Likewise.
* src/gdbmdump.c: Likewise.
* src/gdbmexists.c: Likewise.
* src/gdbmexp.c: Likewise.
* src/gdbmfetch.c: Likewise.
* src/gdbmimp.c: Likewise.
* src/gdbmload.c: Likewise.
* src/gdbmopen.c: Likewise.
* src/gdbmreorg.c: Likewise.
* src/gdbmseq.c: Likewise.
* src/gdbmsetopt.c: Likewise.
* src/gdbmstore.c: Likewise.
* src/gdbmsync.c: Likewise.
* src/mmap.c: Likewise.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | compat/dbminit.c | 2 | ||||
-rw-r--r-- | compat/dbmopen.c | 24 | ||||
-rw-r--r-- | src/bucket.c | 89 | ||||
-rw-r--r-- | src/falloc.c | 81 | ||||
-rw-r--r-- | src/findkey.c | 30 | ||||
-rw-r--r-- | src/gdbm.h.in | 1 | ||||
-rw-r--r-- | src/gdbm_load.c | 4 | ||||
-rw-r--r-- | src/gdbmcount.c | 2 | ||||
-rw-r--r-- | src/gdbmdefs.h | 2 | ||||
-rw-r--r-- | src/gdbmdelete.c | 7 | ||||
-rw-r--r-- | src/gdbmdump.c | 14 | ||||
-rw-r--r-- | src/gdbmerrno.c | 8 | ||||
-rw-r--r-- | src/gdbmexists.c | 2 | ||||
-rw-r--r-- | src/gdbmexp.c | 12 | ||||
-rw-r--r-- | src/gdbmfetch.c | 4 | ||||
-rw-r--r-- | src/gdbmimp.c | 10 | ||||
-rw-r--r-- | src/gdbmload.c | 12 | ||||
-rw-r--r-- | src/gdbmopen.c | 48 | ||||
-rw-r--r-- | src/gdbmreorg.c | 26 | ||||
-rw-r--r-- | src/gdbmseq.c | 21 | ||||
-rw-r--r-- | src/gdbmsetopt.c | 40 | ||||
-rw-r--r-- | src/gdbmstore.c | 43 | ||||
-rw-r--r-- | src/gdbmsync.c | 2 | ||||
-rw-r--r-- | src/mmap.c | 6 | ||||
-rw-r--r-- | src/proto.h | 8 | ||||
-rw-r--r-- | src/update.c | 69 |
27 files changed, 363 insertions, 206 deletions
@@ -29,6 +29,8 @@ Instead it sets gdbm_errno to GDBM_MALLOC_ERROR and returns NULL datum. ** gdbm_clear_error +** gdbm_needs_recovery + Version 1.12, 2016-05-16 diff --git a/compat/dbminit.c b/compat/dbminit.c index f5203d1..526410d 100644 --- a/compat/dbminit.c +++ b/compat/dbminit.c @@ -48,7 +48,7 @@ dbminit (char *file) /* Did we successfully open the file? */ if (_gdbm_file == NULL) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, TRUE); return -1; } } diff --git a/compat/dbmopen.c b/compat/dbmopen.c index af423df..f576b37 100644 --- a/compat/dbmopen.c +++ b/compat/dbmopen.c @@ -71,7 +71,7 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) if (fstat (pagfd, &pagst)) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); /* FIXME: special code? */ + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, TRUE); /* FIXME: special code? */ return -1; } @@ -89,14 +89,14 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) return pagfd; else { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, TRUE); return -1; } } } else { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } } @@ -104,7 +104,7 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) /* ok */; else if (st.st_size != DEF_DIR_SIZE) { - gdbm_set_errno (NULL, GDBM_BAD_MAGIC_NUMBER, 1); + gdbm_set_errno (NULL, GDBM_BAD_MAGIC_NUMBER, FALSE); return -1; } else @@ -112,13 +112,13 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) fd = open (file_name, flags); if (fd == -1) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return fd; } if (read (fd, dirbuf, sizeof (dirbuf)) != sizeof (dirbuf)) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); close (fd); return -1; } @@ -135,7 +135,7 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) return fd; } close (fd); - gdbm_set_errno (NULL, GDBM_BAD_MAGIC_NUMBER, 1); + gdbm_set_errno (NULL, GDBM_BAD_MAGIC_NUMBER, FALSE); return -1; } } @@ -151,7 +151,7 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode) if (write (fd, dirbuf, sizeof (dirbuf)) != sizeof (dirbuf)) { - gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, FALSE); close (fd); fd = -1; } @@ -168,7 +168,7 @@ ndbm_open_dir_file (const char *base, int pagfd, int mode) if (!file_name) { - gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, 1); + gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, FALSE); return -1; } fd = ndbm_open_dir_file0 (strcat (strcpy (file_name, base), DIRSUF), @@ -212,7 +212,7 @@ dbm_open (char *file, int flags, int mode) pag_file = (char *) malloc (strlen (file) + 5); if (!pag_file) { - gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, 1); /* For the hell of it. */ + gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, FALSE); /* For the hell of it. */ return NULL; } @@ -250,7 +250,7 @@ dbm_open (char *file, int flags, int mode) if (!dbm) { free (pag_file); - gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, 1); /* For the hell of it. */ + gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, FALSE); /* For the hell of it. */ return NULL; } @@ -259,7 +259,7 @@ dbm_open (char *file, int flags, int mode) /* Did we successfully open the file? */ if (dbm->file == NULL) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 1); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); free (dbm); dbm = NULL; } diff --git a/src/bucket.c b/src/bucket.c index ee0e157..96ed8b4 100644 --- a/src/bucket.c +++ b/src/bucket.c @@ -49,7 +49,7 @@ _gdbm_new_bucket (GDBM_FILE dbf, hash_bucket *bucket, int bits) bucket. In any case, the requested bucket becomes the "current" bucket and dbf->bucket points to the correct bucket. */ -void +int _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) { int rc; @@ -63,8 +63,11 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) if (dbf->bucket_cache == NULL) { - if(_gdbm_init_cache(dbf, DEFAULT_CACHESIZE) == -1) - _gdbm_fatal(dbf, _("couldn't init cache")); + if (_gdbm_init_cache (dbf, DEFAULT_CACHESIZE) == -1) + { + _gdbm_fatal (dbf, _("couldn't init cache")); + return -1; + } } /* Is that one is not already current, we must find it. */ @@ -77,14 +80,17 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) { dbf->bucket = dbf->bucket_cache[index].ca_bucket; dbf->cache_entry = &dbf->bucket_cache[index]; - return; + return 0; } } /* It is not in the cache, read it from the disk. */ dbf->last_read = (dbf->last_read + 1) % dbf->cache_size; if (dbf->bucket_cache[dbf->last_read].ca_changed) - _gdbm_write_bucket (dbf, &dbf->bucket_cache[dbf->last_read]); + { + if (_gdbm_write_bucket (dbf, &dbf->bucket_cache[dbf->last_read])) + return -1; + } dbf->bucket_cache[dbf->last_read].ca_adr = bucket_adr; dbf->bucket = dbf->bucket_cache[dbf->last_read].ca_bucket; dbf->cache_entry = &dbf->bucket_cache[dbf->last_read]; @@ -94,14 +100,22 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) /* Read the bucket. */ file_pos = __lseek (dbf, bucket_adr, SEEK_SET); if (file_pos != bucket_adr) - _gdbm_fatal (dbf, _("lseek error")); + { + _gdbm_fatal (dbf, _("lseek error")); + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + return -1; + } rc = _gdbm_full_read (dbf, dbf->bucket, dbf->header->bucket_size); if (rc) - _gdbm_fatal (dbf, gdbm_strerror (rc)); + { + _gdbm_fatal (dbf, gdbm_strerror (rc)); + gdbm_set_errno (dbf, rc, TRUE); + return -1; + } } - return; + return 0; } int @@ -131,13 +145,13 @@ _gdbm_read_bucket_at (GDBM_FILE dbf, off_t off, hash_bucket *bucket, file_pos = __lseek (dbf, off, SEEK_SET); if (file_pos != off) { - gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, 1); + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); return -1; } rc = _gdbm_full_read (dbf, bucket, size); if (rc) { - gdbm_set_errno (dbf, rc, 1); + gdbm_set_errno (dbf, rc, TRUE); return -1; } return 0; @@ -147,7 +161,7 @@ _gdbm_read_bucket_at (GDBM_FILE dbf, off_t off, hash_bucket *bucket, a new bucket. This doesn't require any disk reads because all hash values are stored in the buckets. Splitting the current bucket may require doubling the size of the hash directory. */ -void +int _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) { hash_bucket *bucket[2]; /* Pointers to the new buckets. */ @@ -176,14 +190,16 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) bucket_element *old_el; /* Pointer into the old bucket. */ int select; /* Used to index bucket during movement. */ - /* No directories are yet old. */ old_count = 0; if (dbf->bucket_cache == NULL) { - if(_gdbm_init_cache(dbf, DEFAULT_CACHESIZE) == -1) - _gdbm_fatal(dbf, _("couldn't init cache")); + if (_gdbm_init_cache(dbf, DEFAULT_CACHESIZE) == -1) + { + _gdbm_fatal (dbf, _("couldn't init cache")); + return -1; + } } while (dbf->bucket->count == dbf->header->bucket_elems) @@ -197,7 +213,10 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) while (dbf->bucket_cache[cache_0].ca_bucket == dbf->bucket); bucket[0] = dbf->bucket_cache[cache_0].ca_bucket; if (dbf->bucket_cache[cache_0].ca_changed) - _gdbm_write_bucket (dbf, &dbf->bucket_cache[cache_0]); + { + if (_gdbm_write_bucket (dbf, &dbf->bucket_cache[cache_0])) + return -1; + } do { dbf->last_read = (dbf->last_read + 1) % dbf->cache_size; @@ -206,13 +225,20 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) while (dbf->bucket_cache[cache_1].ca_bucket == dbf->bucket); bucket[1] = dbf->bucket_cache[cache_1].ca_bucket; if (dbf->bucket_cache[cache_1].ca_changed) - _gdbm_write_bucket (dbf, &dbf->bucket_cache[cache_1]); + { + if (_gdbm_write_bucket (dbf, &dbf->bucket_cache[cache_1])) + return -1; + } new_bits = dbf->bucket->bucket_bits+1; _gdbm_new_bucket (dbf, bucket[0], new_bits); _gdbm_new_bucket (dbf, bucket[1], new_bits); - adr_0 = _gdbm_alloc (dbf, dbf->header->bucket_size); + adr_0 = _gdbm_alloc (dbf, dbf->header->bucket_size); + if (adr_0 == 0) + return -1; dbf->bucket_cache[cache_0].ca_adr = adr_0; adr_1 = _gdbm_alloc (dbf, dbf->header->bucket_size); + if (adr_1 == 0) + return -1; dbf->bucket_cache[cache_1].ca_adr = adr_1; /* Double the directory size if necessary. */ @@ -220,8 +246,16 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) { dir_size = dbf->header->dir_size * 2; dir_adr = _gdbm_alloc (dbf, dir_size); + if (dir_adr == 0) + return -1; new_dir = (off_t *) malloc (dir_size); - if (new_dir == NULL) _gdbm_fatal (dbf, _("malloc error")); + if (new_dir == NULL) + { + gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, TRUE); + _gdbm_fatal (dbf, _("malloc error")); + return -1; + } + for (index = 0; index < GDBM_DIR_COUNT (dbf); index++) { new_dir[2*index] = dbf->dir[index]; @@ -258,6 +292,8 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) /* Allocate avail space for the bucket[1]. */ bucket[1]->bucket_avail[0].av_adr = _gdbm_alloc (dbf, dbf->header->block_size); + if (bucket[1]->bucket_avail[0].av_adr == 0) + return -1; bucket[1]->bucket_avail[0].av_size = dbf->header->block_size; bucket[1]->av_count = 1; @@ -329,13 +365,15 @@ _gdbm_split_bucket (GDBM_FILE dbf, int next_insert) /* Get rid of old directories. */ for (index = 0; index < old_count; index++) _gdbm_free (dbf, old_adr[index], old_size[index]); + + return 0; } /* The only place where a bucket is written. CA_ENTRY is the cache entry containing the bucket to be written. */ -void +int _gdbm_write_bucket (GDBM_FILE dbf, cache_elem *ca_entry) { int rc; @@ -343,12 +381,21 @@ _gdbm_write_bucket (GDBM_FILE dbf, cache_elem *ca_entry) file_pos = __lseek (dbf, ca_entry->ca_adr, SEEK_SET); if (file_pos != ca_entry->ca_adr) - _gdbm_fatal (dbf, _("lseek error")); + { + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + _gdbm_fatal (dbf, _("lseek error")); + return -1; + } rc = _gdbm_full_write (dbf, ca_entry->ca_bucket, dbf->header->bucket_size); if (rc) - _gdbm_fatal (dbf, gdbm_strerror (rc)); + { + gdbm_set_errno (dbf, rc, TRUE); + _gdbm_fatal (dbf, gdbm_strerror (rc)); + return -1; + } ca_entry->ca_changed = FALSE; ca_entry->ca_data.hash_val = -1; ca_entry->ca_data.elem_loc = -1; + return 0; } diff --git a/src/falloc.c b/src/falloc.c index 32aad51..58a9431 100644 --- a/src/falloc.c +++ b/src/falloc.c @@ -28,8 +28,8 @@ static avail_elem get_elem (int, avail_elem [], int *); static avail_elem get_block (int, GDBM_FILE); -static void push_avail_block (GDBM_FILE); -static void pop_avail_block (GDBM_FILE); +static int push_avail_block (GDBM_FILE); +static int pop_avail_block (GDBM_FILE); static void adjust_bucket_avail (GDBM_FILE); /* Allocate space in the file DBF for a block NUM_BYTES in length. Return @@ -65,7 +65,8 @@ _gdbm_alloc (GDBM_FILE dbf, int num_bytes) something on the stack. */ if ((dbf->header->avail.count <= (dbf->header->avail.size >> 1)) && (dbf->header->avail.next_block != 0)) - pop_avail_block (dbf); + if (pop_avail_block (dbf)) + return 0; /* check the header avail table next */ av_el = get_elem (num_bytes, dbf->header->avail.av_table, @@ -114,7 +115,7 @@ _gdbm_free (GDBM_FILE dbf, off_t file_adr, int num_bytes) { if (dbf->header->avail.count == dbf->header->avail.size) { - push_avail_block (dbf); + push_avail_block (dbf);//FIXME: return } _gdbm_put_av_elem (temp, dbf->header->avail.av_table, &dbf->header->avail.count, dbf->coalesce_blocks); @@ -130,7 +131,7 @@ _gdbm_free (GDBM_FILE dbf, off_t file_adr, int num_bytes) { if (dbf->header->avail.count == dbf->header->avail.size) { - push_avail_block (dbf); + push_avail_block (dbf); //FIXME: return } _gdbm_put_av_elem (temp, dbf->header->avail.av_table, &dbf->header->avail.count, dbf->coalesce_blocks); @@ -155,7 +156,7 @@ _gdbm_free (GDBM_FILE dbf, off_t file_adr, int num_bytes) now called even when the avail block is not empty, so we must be smart about things. */ -static void +static int pop_avail_block (GDBM_FILE dbf) { int rc; @@ -168,7 +169,8 @@ pop_avail_block (GDBM_FILE dbf) { /* We're kind of stuck here, so we re-split the header in order to avoid crashing. Sigh. */ - push_avail_block(dbf); + if (push_avail_block (dbf)) + return -1; } /* Set up variables. */ @@ -178,14 +180,29 @@ pop_avail_block (GDBM_FILE dbf) /* Allocate space for the block. */ new_blk = (avail_block *) malloc (new_el.av_size); - if (new_blk == NULL) _gdbm_fatal(dbf, _("malloc failed")); + if (new_blk == NULL) + { + gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, TRUE); + _gdbm_fatal(dbf, _("malloc failed")); + return -1; + } /* Read the block. */ file_pos = __lseek (dbf, new_el.av_adr, SEEK_SET); - if (file_pos != new_el.av_adr) _gdbm_fatal (dbf, _("lseek error")); + if (file_pos != new_el.av_adr) + { + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + _gdbm_fatal (dbf, _("lseek error")); + return -1; + } + rc = _gdbm_full_read (dbf, new_blk, new_el.av_size); if (rc) - _gdbm_fatal (dbf, gdbm_strerror (rc)); + { + gdbm_set_errno (dbf, rc, TRUE); + _gdbm_fatal (dbf, gdbm_strerror (rc)); + return -1; + } /* Add the elements from the new block to the header. */ index = 0; @@ -195,16 +212,17 @@ pop_avail_block (GDBM_FILE dbf) && dbf->header->avail.count < dbf->header->avail.size) { /* With luck, this will merge a lot of blocks! */ - _gdbm_put_av_elem(new_blk->av_table[index], - dbf->header->avail.av_table, - &dbf->header->avail.count, TRUE); + _gdbm_put_av_elem (new_blk->av_table[index], + dbf->header->avail.av_table, + &dbf->header->avail.count, TRUE); index++; } if (dbf->header->avail.count == dbf->header->avail.size) { /* We're kind of stuck here, so we re-split the header in order to avoid crashing. Sigh. */ - push_avail_block(dbf); + if (push_avail_block (dbf)) + return -1; } } @@ -220,18 +238,21 @@ pop_avail_block (GDBM_FILE dbf) { /* We're kind of stuck here, so we re-split the header in order to avoid crashing. Sigh. */ - push_avail_block(dbf); + if (push_avail_block (dbf)) + return -1; } _gdbm_put_av_elem (new_el, dbf->header->avail.av_table, &dbf->header->avail.count, TRUE); free (new_blk); + + return 0; } /* Splits the header avail block and pushes half onto the avail stack. */ -static void +static int push_avail_block (GDBM_FILE dbf) { int av_size; @@ -253,10 +274,15 @@ push_avail_block (GDBM_FILE dbf) new_loc = get_block (av_size, dbf); av_adr = new_loc.av_adr; - /* Split the header block. */ temp = (avail_block *) malloc (av_size); - if (temp == NULL) _gdbm_fatal (dbf, _("malloc error")); + if (temp == NULL) + { + gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, TRUE); + _gdbm_fatal (dbf, _("malloc error")); + return -1; + } + /* Set the size to be correct AFTER the pop_avail_block. */ temp->size = dbf->header->avail.size; temp->count = 0; @@ -279,14 +305,25 @@ push_avail_block (GDBM_FILE dbf) /* Update the disk. */ file_pos = __lseek (dbf, av_adr, SEEK_SET); - if (file_pos != av_adr) _gdbm_fatal (dbf, _("lseek error")); + if (file_pos != av_adr) + { + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + _gdbm_fatal (dbf, _("lseek error")); + return -1; + } + rc = _gdbm_full_write (dbf, temp, av_size); if (rc) - _gdbm_fatal (dbf, gdbm_strerror (rc)); - free (temp); -} + { + gdbm_set_errno (dbf, rc, TRUE); + _gdbm_fatal (dbf, gdbm_strerror (rc)); + return -1; + } + free (temp); + return 0; +} /* Get_elem returns an element in the AV_TABLE block which is larger than SIZE. AV_COUNT is the number of elements in the diff --git a/src/findkey.c b/src/findkey.c index 6b13fbf..34091e1 100644 --- a/src/findkey.c +++ b/src/findkey.c @@ -54,17 +54,30 @@ _gdbm_read_entry (GDBM_FILE dbf, int elem_loc) data_ca->dptr = (char *) malloc (1); else data_ca->dptr = (char *) malloc (key_size+data_size); - if (data_ca->dptr == NULL) _gdbm_fatal (dbf, _("malloc error")); - + if (data_ca->dptr == NULL) + { + gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, FALSE); + _gdbm_fatal (dbf, _("malloc error")); + return NULL; + } /* Read into the cache. */ file_pos = __lseek (dbf, dbf->bucket->h_table[elem_loc].data_pointer, SEEK_SET); if (file_pos != dbf->bucket->h_table[elem_loc].data_pointer) - _gdbm_fatal (dbf, _("lseek error")); + { + gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + _gdbm_fatal (dbf, _("lseek error")); + return NULL; + } + rc = _gdbm_full_read (dbf, data_ca->dptr, key_size+data_size); if (rc) - _gdbm_fatal (dbf, gdbm_strerror (rc)); + { + gdbm_set_errno (dbf, rc, TRUE); + _gdbm_fatal (dbf, gdbm_strerror (rc)); + return NULL; + } return data_ca->dptr; } @@ -92,8 +105,9 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) new_hash_val = _gdbm_hash (key); if (ret_hash_val) *ret_hash_val = new_hash_val; - _gdbm_get_bucket (dbf, new_hash_val>> (31-dbf->header->dir_bits)); - + if (_gdbm_get_bucket (dbf, new_hash_val >> (31 - dbf->header->dir_bits))) + return -1; + /* Is the element the last one found for this bucket? */ if (dbf->cache_entry->ca_data.elem_loc != -1 && new_hash_val == dbf->cache_entry->ca_data.hash_val @@ -130,6 +144,8 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) /* This may be the one we want. The only way to tell is to read it. */ file_key = _gdbm_read_entry (dbf, elem_loc); + if (!file_key) + return -1; if (memcmp (file_key, key.dptr, key_size) == 0) { /* This is the item. */ @@ -149,7 +165,7 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) } /* If we get here, we never found the key. */ - gdbm_set_errno (dbf, GDBM_ITEM_NOT_FOUND, 0); + gdbm_set_errno (dbf, GDBM_ITEM_NOT_FOUND, FALSE); return -1; } diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 83f99c2..a3d0461 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -183,6 +183,7 @@ extern const char * const gdbm_errlist[]; extern int gdbm_last_errno (GDBM_FILE dbf); extern void gdbm_set_errno (GDBM_FILE dbf, gdbm_error ec, int fatal); extern void gdbm_clear_error (GDBM_FILE dbf); +extern int gdbm_needs_recovery (GDBM_FILE dbf); /* extra prototypes */ diff --git a/src/gdbm_load.c b/src/gdbm_load.c index fd404b9..c4b9ee6 100644 --- a/src/gdbm_load.c +++ b/src/gdbm_load.c @@ -53,13 +53,13 @@ set_meta_info (GDBM_FILE dbf) { if (fchown (fd, owner_uid, owner_gid)) { - gdbm_set_errno (dbf, GDBM_ERR_FILE_OWNER, 0); + gdbm_set_errno (dbf, GDBM_ERR_FILE_OWNER, FALSE); return 1; } } if ((meta_mask & GDBM_META_MASK_MODE) && fchmod (fd, mode)) { - gdbm_set_errno (dbf, GDBM_ERR_FILE_OWNER, 0); + gdbm_set_errno (dbf, GDBM_ERR_FILE_OWNER, FALSE); return 1; } } diff --git a/src/gdbmcount.c b/src/gdbmcount.c index 472f0d3..a301d0c 100644 --- a/src/gdbmcount.c +++ b/src/gdbmcount.c @@ -46,7 +46,7 @@ gdbm_count (GDBM_FILE dbf, gdbm_count_t *pcount) sdir = malloc (dbf->header->dir_size); if (!sdir) { - gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, 0); + gdbm_set_errno (dbf, GDBM_MALLOC_ERROR, FALSE); return -1; } diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h index 34c8b55..ebe412b 100644 --- a/src/gdbmdefs.h +++ b/src/gdbmdefs.h @@ -241,7 +241,7 @@ struct gdbm_file_info { \ if (dbf->need_recovery) \ { \ - gdbm_set_errno (dbf, GDBM_NEED_RECOVERY, 1); \ + gdbm_set_errno (dbf, GDBM_NEED_RECOVERY, TRUE); \ return onerr; \ } \ } \ diff --git a/src/gdbmdelete.c b/src/gdbmdelete.c index faa4957..a735d0d 100644 --- a/src/gdbmdelete.c +++ b/src/gdbmdelete.c @@ -41,12 +41,12 @@ gdbm_delete (GDBM_FILE dbf, datum key) /* First check to make sure this guy is a writer. */ if (dbf->read_write == GDBM_READER) { - gdbm_set_errno (dbf, GDBM_READER_CANT_DELETE, 0); + gdbm_set_errno (dbf, GDBM_READER_CANT_DELETE, FALSE); return -1; } /* Initialize the gdbm_errno variable. */ - gdbm_set_errno (dbf, GDBM_NO_ERROR, 0); + gdbm_set_errno (dbf, GDBM_NO_ERROR, FALSE); /* Find the item. */ elem_loc = _gdbm_findkey (dbf, key, NULL, NULL); @@ -98,6 +98,5 @@ gdbm_delete (GDBM_FILE dbf, datum key) dbf->cache_entry->ca_data.elem_loc = -1; /* Do the writes. */ - _gdbm_end_update (dbf); - return 0; + return _gdbm_end_update (dbf); } diff --git a/src/gdbmdump.c b/src/gdbmdump.c index 49f39bf..d4ec5b6 100644 --- a/src/gdbmdump.c +++ b/src/gdbmdump.c @@ -99,7 +99,7 @@ _gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp) { free (key.dptr); free (data.dptr); - gdbm_set_errno (dbf, rc, 0); + gdbm_set_errno (dbf, rc, FALSE); break; } } @@ -142,13 +142,13 @@ gdbm_dump_to_file (GDBM_FILE dbf, FILE *fp, int format) break; default: - gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, 0); + gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, FALSE); return EINVAL; } if (rc == 0 && ferror (fp)) { - gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, FALSE); rc = -1; } @@ -172,7 +172,7 @@ gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags, nfd = open (filename, O_WRONLY | O_CREAT | O_EXCL, mode); if (nfd == -1) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } break; @@ -180,12 +180,12 @@ gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags, nfd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, mode); if (nfd == -1) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } break; default: - gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, 0); + gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, FALSE); return -1; } @@ -193,7 +193,7 @@ gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags, if (!fp) { close (nfd); - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } rc = gdbm_dump_to_file (dbf, fp, fmt); diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 4eeff8c..8882489 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -50,6 +50,14 @@ gdbm_last_errno (GDBM_FILE dbf) return dbf->last_error; } +int +gdbm_needs_recovery (GDBM_FILE dbf) +{ + if (!dbf) + return 0; + return dbf->need_recovery; +} + /* Clear error state for the database DBF. */ void gdbm_clear_error (GDBM_FILE dbf) diff --git a/src/gdbmexists.c b/src/gdbmexists.c index e44f04e..70ee989 100644 --- a/src/gdbmexists.c +++ b/src/gdbmexists.c @@ -33,7 +33,7 @@ gdbm_exists (GDBM_FILE dbf, datum key) if (_gdbm_findkey (dbf, key, NULL, NULL) < 0) { if (gdbm_errno == GDBM_ITEM_NOT_FOUND) - gdbm_set_errno (dbf, GDBM_NO_ERROR, 0); + gdbm_set_errno (dbf, GDBM_NO_ERROR, FALSE); return 0; } return 1; diff --git a/src/gdbmexp.c b/src/gdbmexp.c index f188040..4092c62 100644 --- a/src/gdbmexp.c +++ b/src/gdbmexp.c @@ -84,7 +84,7 @@ gdbm_export_to_file (GDBM_FILE dbf, FILE *fp) write_fail: - gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_WRITE_ERROR, FALSE); return -1; } @@ -101,7 +101,7 @@ gdbm_export (GDBM_FILE dbf, const char *exportfile, int flags, int mode) nfd = open (exportfile, O_WRONLY | O_CREAT | O_EXCL, mode); if (nfd == -1) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } break; @@ -109,15 +109,15 @@ gdbm_export (GDBM_FILE dbf, const char *exportfile, int flags, int mode) nfd = open (exportfile, O_WRONLY | O_CREAT | O_TRUNC, mode); if (nfd == -1) { - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } break; default: #ifdef GDBM_BAD_OPEN_FLAGS - gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, 0); + gdbm_set_errno (NULL, GDBM_BAD_OPEN_FLAGS, FALSE); #else - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); #endif return -1; } @@ -126,7 +126,7 @@ gdbm_export (GDBM_FILE dbf, const char *exportfile, int flags, int mode) if (!fp) { close (nfd); - gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, 0); + gdbm_set_errno (NULL, GDBM_FILE_OPEN_ERROR, FALSE); return -1; } diff --git a/src/gdbmfetch.c b/src/gdbmfetch.c index 25a6c1d..8deee9c 100644 --- a/src/gdbmfetch.c +++ b/src/gdbmfetch.c @@ -41,7 +41,7 @@ gdbm_fetch (GDBM_FILE dbf, datum key) GDBM_ASSERT_CONSISTENCY (dbf, return_val); /* Initialize the gdbm_errno variable. */ - gdbm_set_errno (dbf, GDBM_NO_ERROR, 0); + gdbm_set_errno (dbf, GDBM_NO_ERROR, F |