summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-07-28 12:20:25 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-07-28 12:20:25 +0300
commit016aaadca5bf994678a56399c63ae0ac28adfc48 (patch)
tree65c56e596be76cfb35fc7c1d4273a52daea4f56d
parent35e81092b99608d8a4f1ecf55c21bbd4d3c5eda0 (diff)
downloadgdbm-016aaadca5bf994678a56399c63ae0ac28adfc48.tar.gz
Introduce extended header.
* src/gdbm.h.in (GDBM_NUMSYNC): New flag for gdbm_open * src/gdbmdefs.h (gdbm_ext_header): New struct. (gdbm_file_header): New member of the union v: gdbm_ext_header. * src/gdbmopen.c (gdbm_header_avail): New function. (validate_header): Use dbf->avail. (gdbm_fd_open): Read both database types. Create GDBM_NUMSYNC_MAGIC database if given the GDBM_MAGIC flag.
-rw-r--r--src/gdbm.h.in2
-rw-r--r--src/gdbmdefs.h13
-rw-r--r--src/gdbmopen.c75
3 files changed, 64 insertions, 26 deletions
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index 1bff4a7..f6a457a 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -56,7 +56,9 @@ extern "C" {
# define GDBM_CLOERROR 0x0400 /* Only for gdbm_fd_open: close fd on error. */
# define GDBM_XVERIFY 0x0800 /* Additional consistency checks. */
# define GDBM_PREREAD 0x1000 /* Enable pre-fault reading of mmapped regions. */
+# define GDBM_NUMSYNC 0x2000
+
/* Parameters to gdbm_store for simple insertion or replacement in the
case that the key is already in the database. */
# define GDBM_INSERT 0 /* Never replace old data with new. */
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index c5fbb18..25ea6d9 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -72,6 +72,12 @@ typedef struct
typedef struct
{
+ unsigned numsync; /* Number of synchronizations */
+ avail_block avail_tab;
+} gdbm_ext_header;
+
+typedef struct
+{
int header_magic; /* Version of file. */
int block_size; /* The optimal i/o blocksize from stat. */
off_t dir; /* File address of hash directory table. */
@@ -82,9 +88,10 @@ typedef struct
off_t next_block; /* The next unallocated block address. */
union
{
- avail_block avail_tab; /* This must be last because of the pseudo
- array in avail. This avail grows to fill
- the entire block. */
+ gdbm_ext_header ext;
+ avail_block avail_tab; /* This must be last because of the pseudo
+ array in avail. This avail grows to fill
+ the entire block. */
} v;
} gdbm_file_header;
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index a532b93..54fcabc 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -59,11 +59,31 @@ bucket_element_count (size_t bucket_size)
return (bucket_size - sizeof (hash_bucket)) / sizeof (bucket_element) + 1;
}
+static void
+gdbm_header_avail (gdbm_file_header const *hdr,
+ avail_block **avail_ptr, size_t *avail_size)
+{
+ switch (hdr->header_magic)
+ {
+ case GDBM_OMAGIC:
+ case GDBM_MAGIC:
+ *avail_ptr = (avail_block *) &hdr->v.avail_tab;
+ *avail_size = (hdr->block_size - offsetof (gdbm_file_header, v.avail_tab));
+ break;
+
+ case GDBM_NUMSYNC_MAGIC:
+ *avail_ptr = (avail_block *) &hdr->v.ext.avail_tab;
+ *avail_size = (hdr->block_size - offsetof (gdbm_file_header, v.ext.avail_tab));
+ break;
+ }
+}
+
static int
validate_header_std (gdbm_file_header const *hdr, struct stat const *st)
{
int result = GDBM_NO_ERROR;
-
+ int dir_size, dir_bits;
+
if (!(hdr->block_size > 0
&& hdr->block_size > sizeof (gdbm_file_header)
&& hdr->block_size - sizeof (gdbm_file_header) >=
@@ -95,13 +115,13 @@ validate_header_std (gdbm_file_header const *hdr, struct stat const *st)
if (hdr->dir_bits != dir_bits)
return GDBM_BAD_HEADER;
- if (!(hdr->bucket_size > sizeof(hash_bucket)))
+ if (!(hdr->bucket_size > sizeof (hash_bucket)))
return GDBM_BAD_HEADER;
if (hdr->bucket_elems != bucket_element_count (hdr->bucket_size))
return GDBM_BAD_HEADER;
- if (((hdr->block_size - sizeof (gdbm_file_header)) / sizeof(avail_elem) + 1)
+ if (((hdr->block_size - sizeof (gdbm_file_header)) / sizeof (avail_elem) + 1)
!= hdr->v.avail_tab.size)
return GDBM_BAD_HEADER;
@@ -112,9 +132,12 @@ static int
validate_header_numsync (gdbm_file_header const *hdr, struct stat const *st)
{
int result = GDBM_NO_ERROR;
-
+ int dir_size, dir_bits;
+
if (!(hdr->block_size > 0
- && hdr->block_size > sizeof (gdbm_file_header))) //FIXME
+ && hdr->block_size > sizeof (gdbm_file_header)
+ && hdr->block_size - sizeof (gdbm_file_header) >=
+ sizeof(hdr->v.ext.avail_tab.av_table[0])))
{
return GDBM_BLOCK_SIZE_ERROR;
}
@@ -142,21 +165,22 @@ validate_header_numsync (gdbm_file_header const *hdr, struct stat const *st)
if (hdr->dir_bits != dir_bits)
return GDBM_BAD_HEADER;
- if (!(hdr->bucket_size > sizeof(hash_bucket)))
+ if (!(hdr->bucket_size > sizeof (hash_bucket)))
return GDBM_BAD_HEADER;
if (hdr->bucket_elems != bucket_element_count (hdr->bucket_size))
return GDBM_BAD_HEADER;
- //FIXME: Verify avail offset
+ if (((hdr->block_size - sizeof (gdbm_file_header)) / sizeof (avail_elem) + 1)
+ != hdr->v.ext.avail_tab.size)
+ return GDBM_BAD_HEADER;
+
return result;
}
static int
validate_header (gdbm_file_header const *hdr, struct stat const *st)
{
- int dir_size, dir_bits;
-
/* Is the magic number good? */
switch (hdr->header_magic)
{
@@ -201,7 +225,7 @@ _gdbm_validate_header (GDBM_FILE dbf)
rc = validate_header (dbf->header, &file_stat);
if (rc == 0)
{
- if (gdbm_avail_block_validate (dbf, &dbf->header->v.avail_tab,
+ if (gdbm_avail_block_validate (dbf, dbf->avail,
GDBM_HEADER_AVAIL_SIZE (dbf)))
rc = GDBM_BAD_AVAIL;
}
@@ -415,8 +439,16 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
}
/* Set the magic number and the block_size. */
- dbf->header->header_magic = GDBM_MAGIC;
+ if (flags & GDBM_NUMSYNC)
+ dbf->header->header_magic = GDBM_NUMSYNC_MAGIC;
+ else
+ dbf->header->header_magic = GDBM_MAGIC;
+
+ /*
+ * Set block size. It must be initialized for gdbm_header_avail to work.
+ */
dbf->header->block_size = block_size;
+ gdbm_header_avail (dbf->header, &dbf->avail, &dbf->avail_size);
dbf->header->dir_size = dir_size;
dbf->header->dir_bits = dir_bits;
@@ -454,11 +486,11 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
dbf->dir[index] = 2*dbf->header->block_size;
/* Initialize the active avail block. */
- dbf->header->v.avail_tab.size
- = ( (dbf->header->block_size - sizeof (gdbm_file_header))
- / sizeof (avail_elem)) + 1;
- dbf->header->v.avail_tab.count = 0;
- dbf->header->v.avail_tab.next_block = 0;
+ dbf->avail->size = (dbf->avail_size - offsetof(avail_block, av_table))
+ / sizeof (avail_elem);
+ dbf->avail->count = 0;
+ dbf->avail->next_block = 0;
+
dbf->header->next_block = 4*dbf->header->block_size;
/* Write initial configuration to the file. */
@@ -561,7 +593,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
}
memcpy (dbf->header, &partial_header, sizeof (partial_header));
- if (_gdbm_full_read (dbf, &dbf->header->v.avail_tab.av_table[1],
+ if (_gdbm_full_read (dbf, dbf->header + 1,
dbf->header->block_size - sizeof (gdbm_file_header)))
{
if (!(flags & GDBM_CLOERROR))
@@ -569,8 +601,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
SAVE_ERRNO (gdbm_close (dbf));
return NULL;
}
-
- if (gdbm_avail_block_validate (dbf, &dbf->header->v.avail_tab,
+ gdbm_header_avail (dbf->header, &dbf->avail, &dbf->avail_size);
+
+ if (gdbm_avail_block_validate (dbf, dbf->avail,
GDBM_HEADER_AVAIL_SIZE (dbf)))
{
if (!(flags & GDBM_CLOERROR))
@@ -614,10 +647,6 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
}
- //FIXME dbf->avail_off = offsetof (gdbm_file_header, avail_tab);
- dbf->avail = &dbf->header->v.avail_tab;
- dbf->avail_size = (dbf->header->block_size - offsetof (gdbm_file_header, v.avail_tab));
-
#if HAVE_MMAP
if (!(flags & GDBM_NOMMAP))
{