diff options
Diffstat (limited to 'src/findkey.c')
-rw-r--r-- | src/findkey.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/findkey.c b/src/findkey.c index 7638b04..bd9fd83 100644 --- a/src/findkey.c +++ b/src/findkey.c | |||
@@ -1,89 +1,109 @@ | |||
1 | /* findkey.c - The routine that finds a key entry in the file. */ | 1 | /* findkey.c - The routine that finds a key entry in the file. */ |
2 | 2 | ||
3 | /* This file is part of GDBM, the GNU data base manager. | 3 | /* This file is part of GDBM, the GNU data base manager. |
4 | Copyright (C) 1990-1991, 1993, 2007, 2011, 2013, 2016-2018 Free | 4 | Copyright (C) 1990-1991, 1993, 2007, 2011, 2013, 2016-2018 Free |
5 | Software Foundation, Inc. | 5 | Software Foundation, Inc. |
6 | 6 | ||
7 | GDBM is free software; you can redistribute it and/or modify | 7 | GDBM is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3, or (at your option) | 9 | the Free Software Foundation; either version 3, or (at your option) |
10 | any later version. | 10 | any later version. |
11 | 11 | ||
12 | GDBM is distributed in the hope that it will be useful, | 12 | GDBM is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. | 15 | GNU General Public License for more details. |
16 | 16 | ||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
18 | along with GDBM. If not, see <http://www.gnu.org/licenses/>. */ | 18 | along with GDBM. If not, see <http://www.gnu.org/licenses/>. */ |
19 | 19 | ||
20 | /* Include system configuration before all else. */ | 20 | /* Include system configuration before all else. */ |
21 | #include "autoconf.h" | 21 | #include "autoconf.h" |
22 | 22 | ||
23 | #include "gdbmdefs.h" | 23 | #include "gdbmdefs.h" |
24 | 24 | ||
25 | int | ||
26 | gdbm_bucket_element_valid_p (GDBM_FILE dbf, int elem_loc) | ||
27 | { | ||
28 | return | ||
29 | elem_loc < dbf->header->bucket_elems | ||
30 | && dbf->bucket->h_table[elem_loc].hash_value != -1 | ||
31 | && dbf->bucket->h_table[elem_loc].key_size >= 0 | ||
32 | && off_t_sum_ok (dbf->bucket->h_table[elem_loc].data_pointer, | ||
33 | dbf->bucket->h_table[elem_loc].key_size) | ||
34 | && dbf->bucket->h_table[elem_loc].data_size >= 0 | ||
35 | && off_t_sum_ok (dbf->bucket->h_table[elem_loc].data_pointer | ||
36 | + dbf->bucket->h_table[elem_loc].key_size, | ||
37 | dbf->bucket->h_table[elem_loc].data_size); | ||
38 | } | ||
25 | 39 | ||
26 | /* Read the data found in bucket entry ELEM_LOC in file DBF and | 40 | /* Read the data found in bucket entry ELEM_LOC in file DBF and |
27 | return a pointer to it. Also, cache the read value. */ | 41 | return a pointer to it. Also, cache the read value. */ |
28 | 42 | ||
29 | char * | 43 | char * |
30 | _gdbm_read_entry (GDBM_FILE dbf, int elem_loc) | 44 | _gdbm_read_entry (GDBM_FILE dbf, int elem_loc) |
31 | { | 45 | { |
32 | int rc; | 46 | int rc; |
33 | int key_size; | 47 | int key_size; |
34 | int data_size; | 48 | int data_size; |
35 | off_t file_pos; | 49 | off_t file_pos; |
36 | data_cache_elem *data_ca; | 50 | data_cache_elem *data_ca; |
37 | 51 | ||
38 | /* Is it already in the cache? */ | 52 | /* Is it already in the cache? */ |
39 | if (dbf->cache_entry->ca_data.elem_loc == elem_loc) | 53 | if (dbf->cache_entry->ca_data.elem_loc == elem_loc) |
40 | return dbf->cache_entry->ca_data.dptr; | 54 | return dbf->cache_entry->ca_data.dptr; |
41 | 55 | ||
56 | if (!gdbm_bucket_element_valid_p (dbf, elem_loc)) | ||
57 | { | ||
58 | GDBM_SET_ERRNO (dbf, GDBM_BAD_HASH_TABLE, TRUE); | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
42 | /* Set sizes and pointers. */ | 62 | /* Set sizes and pointers. */ |
43 | key_size = dbf->bucket->h_table[elem_loc].key_size; | 63 | key_size = dbf->bucket->h_table[elem_loc].key_size; |
44 | data_size = dbf->bucket->h_table[elem_loc].data_size; | 64 | data_size = dbf->bucket->h_table[elem_loc].data_size; |
45 | data_ca = &dbf->cache_entry->ca_data; | 65 | data_ca = &dbf->cache_entry->ca_data; |
46 | 66 | ||
47 | /* Set up the cache. */ | 67 | /* Set up the cache. */ |
48 | if (data_ca->dptr != NULL) free (data_ca->dptr); | 68 | if (data_ca->dptr != NULL) free (data_ca->dptr); |
49 | data_ca->key_size = key_size; | 69 | data_ca->key_size = key_size; |
50 | data_ca->data_size = data_size; | 70 | data_ca->data_size = data_size; |
51 | data_ca->elem_loc = elem_loc; | 71 | data_ca->elem_loc = elem_loc; |
52 | data_ca->hash_val = dbf->bucket->h_table[elem_loc].hash_value; | 72 | data_ca->hash_val = dbf->bucket->h_table[elem_loc].hash_value; |
53 | 73 | ||
54 | if (GDBM_DEBUG_HOOK ("_gdbm_read_entry:malloc-failure")) | 74 | if (GDBM_DEBUG_HOOK ("_gdbm_read_entry:malloc-failure")) |
55 | data_ca->dptr = NULL; | 75 | data_ca->dptr = NULL; |
56 | else if (key_size + data_size == 0) | 76 | else if (key_size + data_size == 0) |
57 | data_ca->dptr = (char *) malloc (1); | 77 | data_ca->dptr = (char *) malloc (1); |
58 | else | 78 | else |
59 | data_ca->dptr = (char *) malloc (key_size + data_size); | 79 | data_ca->dptr = (char *) malloc (key_size + data_size); |
60 | if (data_ca->dptr == NULL) | 80 | if (data_ca->dptr == NULL) |
61 | { | 81 | { |
62 | GDBM_SET_ERRNO2 (dbf, GDBM_MALLOC_ERROR, FALSE, GDBM_DEBUG_LOOKUP); | 82 | GDBM_SET_ERRNO2 (dbf, GDBM_MALLOC_ERROR, FALSE, GDBM_DEBUG_LOOKUP); |
63 | _gdbm_fatal (dbf, _("malloc error")); | 83 | _gdbm_fatal (dbf, _("malloc error")); |
64 | return NULL; | 84 | return NULL; |
65 | } | 85 | } |
66 | 86 | ||
67 | /* Read into the cache. */ | 87 | /* Read into the cache. */ |
68 | file_pos = GDBM_DEBUG_OVERRIDE ("_gdbm_read_entry:lseek-failure", | 88 | file_pos = GDBM_DEBUG_OVERRIDE ("_gdbm_read_entry:lseek-failure", |
69 | __lseek (dbf, dbf->bucket->h_table[elem_loc].data_pointer, | 89 | __lseek (dbf, dbf->bucket->h_table[elem_loc].data_pointer, |
70 | SEEK_SET)); | 90 | SEEK_SET)); |
71 | if (file_pos != dbf->bucket->h_table[elem_loc].data_pointer) | 91 | if (file_pos != dbf->bucket->h_table[elem_loc].data_pointer) |
72 | { | 92 | { |
73 | GDBM_SET_ERRNO2 (dbf, GDBM_FILE_SEEK_ERROR, TRUE, GDBM_DEBUG_LOOKUP); | 93 | GDBM_SET_ERRNO2 (dbf, GDBM_FILE_SEEK_ERROR, TRUE, GDBM_DEBUG_LOOKUP); |
74 | _gdbm_fatal (dbf, _("lseek error")); | 94 | _gdbm_fatal (dbf, _("lseek error")); |
75 | return NULL; | 95 | return NULL; |
76 | } | 96 | } |
77 | 97 | ||
78 | rc = GDBM_DEBUG_OVERRIDE ("_gdbm_read_entry:read-failure", | 98 | rc = GDBM_DEBUG_OVERRIDE ("_gdbm_read_entry:read-failure", |
79 | _gdbm_full_read (dbf, data_ca->dptr, key_size+data_size)); | 99 | _gdbm_full_read (dbf, data_ca->dptr, key_size+data_size)); |
80 | if (rc) | 100 | if (rc) |
81 | { | 101 | { |
82 | GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_LOOKUP|GDBM_DEBUG_READ, | 102 | GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_LOOKUP|GDBM_DEBUG_READ, |
83 | "%s: error reading entry: %s", | 103 | "%s: error reading entry: %s", |
84 | dbf->name, gdbm_db_strerror (dbf)); | 104 | dbf->name, gdbm_db_strerror (dbf)); |
85 | dbf->need_recovery = TRUE; | 105 | dbf->need_recovery = TRUE; |
86 | _gdbm_fatal (dbf, gdbm_db_strerror (dbf)); | 106 | _gdbm_fatal (dbf, gdbm_db_strerror (dbf)); |
87 | return NULL; | 107 | return NULL; |
88 | } | 108 | } |
89 | 109 | ||