summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-07-30 07:24:18 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-07-30 07:24:18 +0300
commita9984547d57a687da75f9a182ce2d9b3c5a4cad6 (patch)
tree169a8dc9adea2b1d4556a2eb33ed3938fa577f04
parentb53745b01e90c3d2a5e6d3223f9daedf27cfd88d (diff)
downloadgdbm-a9984547d57a687da75f9a182ce2d9b3c5a4cad6.tar.gz
Avoid eventual alignment problems
* src/gdbm.magic: Handle extended GDBM format. * src/gdbmdefs.h (gdbm_file_standard_header) (gdbm_file_extended_header): New data types. * src/gdbmopen.c (gdbm_header_avail): Use casts to gdbm_file_*_header to obtain data offsets. * src/gdbmtool.c (print_header_handler): Improve formatting.
-rw-r--r--src/gdbm.h.in2
-rw-r--r--src/gdbm.magic40
-rw-r--r--src/gdbmdefs.h34
-rw-r--r--src/gdbmopen.c16
-rw-r--r--src/gdbmtool.c13
5 files changed, 75 insertions, 30 deletions
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index c4c8d88..ac71810 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -56,7 +56,7 @@ 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
+# define GDBM_NUMSYNC 0x2000 /* Enable the numsync extension */
/* Parameters to gdbm_store for simple insertion or replacement in the
diff --git a/src/gdbm.magic b/src/gdbm.magic
index df3dc91..f685481 100644
--- a/src/gdbm.magic
+++ b/src/gdbm.magic
@@ -15,7 +15,7 @@
# along with GDBM. If not, see <http://www.gnu.org/licenses/>.
0 lelong 0x13579acf GNU DBM 64-bit, little endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
>4 lelong x \b; block size=%d
>8 lequad x \b; dir offset=%lld
>16 lelong x \b, size=%d
@@ -24,7 +24,7 @@
>28 lelong x \b, elts=%d
0 belong 0x13579acf GNU DBM 64-bit, big endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
>4 belong x \b; block size=%d
>8 bequad x \b; dir offset=%lld
>16 belong x \b, size=%d
@@ -33,16 +33,16 @@
>28 belong x \b, elts=%d
0 lelong 0x13579acd GNU DBM 32-bit, little endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
0 belong 0x13579acd GNU DBM 32-bit, big endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
0 lelong 0x13579ace GNU DBM old format, little endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
0 belong 0x13579ace GNU DBM old format, big endian
-!:mime application/octet-stream
+!:mime application/x-gdbm
0 string \!\r\n
>3 string \!\040GDBM\040FLAT\040FILE\040DUMP\040--\040THIS\040IS\040NOT\040A\040TEXT\040FILE\r\n GDBM flat dump file
@@ -58,3 +58,31 @@
>>&0 string >\0 \b, for file %s
>0 string #\040GDBM\040dump\040file\040created\040by\040GDBM\040version\040
>>&0 regex ([0-9.]+)\. \b, created by GDBM version %s
+
+0 lelong 0x13579ad1 GNU DBM extended 64-bit, little endian
+!:mime application/x-gdbm
+>4 lelong x \b; block size=%d
+>8 lequad x \b; dir offset=%lld
+>16 lelong x \b, size=%d
+>20 lelong x \b, bits=%d
+>24 lelong x \b; bucket size=%d
+>28 lelong x \b, elts=%d
+>40 lelong x \b, version=%d
+>44 lelong x \b, numsync=%u
+
+0 belong 0x13579ad1 GNU DBM extended 64-bit, big endian
+!:mime application/x-gdbm
+>4 belong x \b; block size=%d
+>8 bequad x \b; dir offset=%lld
+>16 belong x \b, size=%d
+>20 belong x \b, bits=%d
+>24 belong x \b; bucket size=%d
+>28 belong x \b, elts=%d
+>40 belong x \b, version=%d
+>44 belong x \b, numsync=%u
+
+0 lelong 0x13579ad0 GNU DBM extended 32-bit, little endian
+!:mime application/x-gdbm
+
+0 belong 0x13579ad0 GNU DBM extended 32-bit, big endian
+!:mime application/x-gdbm
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index a9c0c7f..ca88902 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -84,13 +84,6 @@ typedef struct
typedef struct
{
- int version;
- unsigned numsync; /* Number of synchronizations */
- int pad[6];
-} 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. */
@@ -99,13 +92,30 @@ typedef struct
int bucket_size; /* Size in bytes of a hash bucket struct. */
int bucket_elems; /* Number of elements in a hash bucket. */
off_t next_block; /* The next unallocated block address. */
- /* In traditional GDBM database file, this header is followed by
- avail_block with av_table occupying the rest of the disk block.
-
- In extended GDBM database file, it is followed by a gdbm_ext_header,
- and then by avail_block. */
} gdbm_file_header;
+/* The extension header keeps additional information. */
+typedef struct
+{
+ int version; /* Version number (currently 0). */
+ unsigned numsync; /* Number of synchronizations. */
+ int pad[6]; /* Reserve space for further use. */
+} gdbm_ext_header;
+
+/* Standard GDBM file header. */
+typedef struct
+{
+ gdbm_file_header hdr;
+ avail_block avail;
+} gdbm_file_standard_header;
+
+/* Extended GDBM file header. */
+typedef struct
+{
+ gdbm_file_header hdr;
+ gdbm_ext_header ext;
+ avail_block avail;
+} gdbm_file_extended_header;
/* The dbm hash bucket element contains the full 31 bit hash value, the
"pointer" to the key and data (stored together) with their sizes. It also
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 14685bc..360d113 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -57,15 +57,17 @@ gdbm_header_avail (gdbm_file_header const *hdr,
{
case GDBM_OMAGIC:
case GDBM_MAGIC:
- *avail_ptr = (avail_block *) (hdr + 1);
- *avail_size = (hdr->block_size - sizeof (gdbm_file_header));
*exhdr = NULL;
+ *avail_ptr = &((gdbm_file_standard_header*)hdr)->avail;
+ *avail_size = (hdr->block_size -
+ offsetof (gdbm_file_standard_header, avail));
break;
case GDBM_NUMSYNC_MAGIC:
- *exhdr = (gdbm_ext_header *) (hdr + 1);
- *avail_ptr = (avail_block *) (*exhdr + 1);
- *avail_size = (hdr->block_size - (sizeof (gdbm_file_header) + sizeof (gdbm_ext_header)));
+ *exhdr = &((gdbm_file_extended_header*)hdr)->ext;
+ *avail_ptr = &((gdbm_file_extended_header*)hdr)->avail;
+ *avail_size = (hdr->block_size -
+ offsetof (gdbm_file_extended_header, avail));
break;
}
}
@@ -587,7 +589,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
}
gdbm_header_avail (dbf->header, &dbf->avail, &dbf->avail_size, &dbf->xheader);
- if (((dbf->header->block_size - (((char*)dbf->avail-(char*)dbf->header) + sizeof (avail_block))) / sizeof (avail_elem) + 1) != dbf->avail->size)
+ if (((dbf->header->block_size -
+ (((char*)dbf->avail - (char*)dbf->header) +
+ sizeof (avail_block))) / sizeof (avail_elem) + 1) != dbf->avail->size)
{
if (!(flags & GDBM_CLOERROR))
dbf->desc = -1;
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 10a5c03..c734ad3 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -790,15 +790,15 @@ print_header_handler (struct handler_param *param)
switch (gdbm_file->header->header_magic)
{
case GDBM_OMAGIC:
- type = "Old GDBM";
+ type = "GDBM (old)";
break;
case GDBM_MAGIC:
- type = "GDBM";
+ type = "GDBM (standard)";
break;
case GDBM_NUMSYNC_MAGIC:
- type = "GDBM numsync";
+ type = "GDBM (numsync)";
break;
default:
@@ -823,9 +823,12 @@ print_header_handler (struct handler_param *param)
fprintf (fp, _(" avail nx blk = %lu\n"),
(unsigned long) gdbm_file->avail->next_block);
- // FIXME
if (gdbm_file->xheader)
- fprintf (fp, _(" numsync = %u\n"), gdbm_file->xheader->numsync);
+ {
+ fprintf (fp, _("\nExtended Header: \n\n"));
+ fprintf (fp, _(" version = %d\n"), gdbm_file->xheader->version);
+ fprintf (fp, _(" numsync = %u\n"), gdbm_file->xheader->numsync);
+ }
}
static void