diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-07-30 07:24:18 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-07-30 07:24:18 +0300 |
commit | a9984547d57a687da75f9a182ce2d9b3c5a4cad6 (patch) | |
tree | 169a8dc9adea2b1d4556a2eb33ed3938fa577f04 | |
parent | b53745b01e90c3d2a5e6d3223f9daedf27cfd88d (diff) | |
download | gdbm-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.in | 2 | ||||
-rw-r--r-- | src/gdbm.magic | 40 | ||||
-rw-r--r-- | src/gdbmdefs.h | 34 | ||||
-rw-r--r-- | src/gdbmopen.c | 16 | ||||
-rw-r--r-- | src/gdbmtool.c | 13 |
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 |