diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-07-28 12:20:25 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-07-28 12:20:25 +0300 |
commit | 016aaadca5bf994678a56399c63ae0ac28adfc48 (patch) | |
tree | 65c56e596be76cfb35fc7c1d4273a52daea4f56d | |
parent | 35e81092b99608d8a4f1ecf55c21bbd4d3c5eda0 (diff) | |
download | gdbm-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.in | 2 | ||||
-rw-r--r-- | src/gdbmdefs.h | 13 | ||||
-rw-r--r-- | src/gdbmopen.c | 75 |
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)) { |