aboutsummaryrefslogtreecommitdiff
path: root/src/gdbmopen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdbmopen.c')
-rw-r--r--src/gdbmopen.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 677f1cf..9747517 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -56,21 +56,52 @@ bucket_element_count (size_t bucket_size)
56 return (bucket_size - sizeof (hash_bucket)) / sizeof (bucket_element) + 1; 56 return (bucket_size - sizeof (hash_bucket)) / sizeof (bucket_element) + 1;
57} 57}
58 58
59static int
60avail_comp (void const *a, void const *b)
61{
62 avail_elem const *ava = a;
63 avail_elem const *avb = b;
64 return ava->av_size - avb->av_size;
65}
66
67/* Returns true if the avail array AV[0]@COUNT is valid.
68
69 As a side effect, ensures the array is sorted by element size
70 in increasing order and restores the ordering if necessary.
71
72 The proper ordering could have been clobbered in versions of GDBM<=1.14,
73 by a call to _gdbm_put_av_elem with the can_merge parameter set to
74 TRUE. This happened in two cases: either because the GDBM_COALESCEBLKS
75 was set, and (quite unfortunately) when _gdbm_put_av_elem was called
76 from pop_avail_block in falloc.c. The latter case is quite common,
77 which means that there can be lots of existing databases with broken
78 ordering of avail arrays. Thus, restoring of the proper ordering
79 is essential for people to be able to use their existing databases.
80*/
59int 81int
60gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem const *av, int count) 82gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem *av, int count)
61{ 83{
62 off_t prev = 0; 84 off_t prev = 0;
63 int i; 85 int i;
64 86 int needs_sorting = 0;
87
65 prev = 0; 88 prev = 0;
66 for (i = 0; i < count; i++, av++) 89 for (i = 0; i < count; i++, av++)
67 { 90 {
68 if (!(av->av_size >= prev 91 if (!(av->av_adr >= dbf->header->bucket_size
69 && av->av_adr >= dbf->header->bucket_size
70 && av->av_adr + av->av_size <= dbf->header->next_block)) 92 && av->av_adr + av->av_size <= dbf->header->next_block))
71 return 0; 93 return 0;
94 if (av->av_size < prev)
95 needs_sorting = 1;
72 prev = av->av_size; 96 prev = av->av_size;
73 } 97 }
98
99 if (needs_sorting && dbf->read_write)
100 {
101 GDBM_DEBUG (GDBM_DEBUG_ERR, "restoring sort order");
102 qsort (av, count, sizeof av[0], avail_comp);
103 }
104
74 return 1; 105 return 1;
75} 106}
76 107

Return to:

Send suggestions and report system problems to the System administrator.