diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-30 14:04:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-30 14:04:48 +0300 |
commit | 4e819c987988432ef936c6c3e003db6b26463154 (patch) | |
tree | feefee7688cec0df1a66401b9da2204272d8d83f | |
parent | b8d5da4c426b21ca0e56fc1cd6f75b49c0668e95 (diff) | |
download | gdbm-4e819c987988432ef936c6c3e003db6b26463154.tar.gz gdbm-4e819c987988432ef936c6c3e003db6b26463154.tar.bz2 |
Fix the legacy operation (--disable-mmapped-io)
* src/mmap.c (_gdbm_file_extend): Move to ...
* src/fullio.c: ... here
* src/proto.h (_gdbm_file_extend): New proto.
* src/gdbmopen.c (gdbm_fd_open): Make sure the file size equals
header->next_block.
* src/gdbmsetopt.c [!HAVE_MMAP]: Don't disable GDBM_GETFLAGS.
* src/update.c (_gdbm_end_update): Make sure disk file ends on
header->next_block.
-rw-r--r-- | src/fullio.c | 46 | ||||
-rw-r--r-- | src/gdbmopen.c | 15 | ||||
-rw-r--r-- | src/gdbmsetopt.c | 4 | ||||
-rw-r--r-- | src/mmap.c | 42 | ||||
-rw-r--r-- | src/proto.h | 1 | ||||
-rw-r--r-- | src/update.c | 2 |
6 files changed, 64 insertions, 46 deletions
diff --git a/src/fullio.c b/src/fullio.c index 84eea60..0efa96d 100644 --- a/src/fullio.c +++ b/src/fullio.c @@ -72,6 +72,52 @@ _gdbm_full_write (GDBM_FILE dbf, void *buffer, size_t size) } ptr += wrbytes; size -= wrbytes; } return 0; } + +/* Grow the disk file of DBF to SIZE bytes in length. Fill the + newly allocated space with zeros. */ +int +_gdbm_file_extend (GDBM_FILE dbf, off_t size) +{ + size_t page_size = sysconf (_SC_PAGESIZE); + char *buf; + off_t file_end; + + file_end = lseek (dbf->desc, 0, SEEK_END); + if (!file_end) + { + GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, FALSE); + return -1; + } + size -= file_end; + if (size > 0) + { + if (size < page_size) + page_size = size; + buf = calloc (1, page_size); + if (!buf) + { + GDBM_SET_ERRNO (dbf, GDBM_MALLOC_ERROR, FALSE); + return -1; + } + + while (size) + { + ssize_t n = write (dbf->desc, buf, + size < page_size ? size : page_size); + if (n <= 0) + { + GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); + break; + } + size -= n; + } + free (buf); + if (size) + return -1; + } + return 0; +} + diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 53d62a4..31d8fea 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -136,13 +136,13 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) return GDBM_BLOCK_SIZE_ERROR; } if (hdr->next_block != st->st_size) /* FIXME: Should return GDBM_NEED_RECOVERY instead? */ return GDBM_BAD_HEADER; - + /* Make sure dir and dir + dir_size fall within the file boundary */ if (!(hdr->dir > 0 && hdr->dir < st->st_size && hdr->dir_size > 0 && hdr->dir + hdr->dir_size < st->st_size)) return GDBM_BAD_HEADER; @@ -424,13 +424,24 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->name, gdbm_db_strerror (dbf)); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); return NULL; } - + + if (_gdbm_file_extend (dbf, dbf->header->next_block)) + { + GDBM_DEBUG (GDBM_DEBUG_OPEN|GDBM_DEBUG_ERR, + "%s: error extending file: %s", + dbf->name, gdbm_db_strerror (dbf)); + if (!(flags & GDBM_CLOERROR)) + dbf->desc = -1; + SAVE_ERRNO (gdbm_close (dbf)); + return NULL; + } + /* Wait for initial configuration to be written to disk. */ gdbm_file_sync (dbf); free (dbf->bucket); } else diff --git a/src/gdbmsetopt.c b/src/gdbmsetopt.c index 69e244c..f9face0 100644 --- a/src/gdbmsetopt.c +++ b/src/gdbmsetopt.c @@ -245,12 +245,13 @@ setopt_gdbm_getmaxmapsize (GDBM_FILE dbf, void *optval, int optlen) GDBM_SET_ERRNO (dbf, GDBM_OPT_ILLEGAL, FALSE); return -1; } *(size_t*) optval = dbf->mapped_size_max; return 0; } +#endif static int setopt_gdbm_getflags (GDBM_FILE dbf, void *optval, int optlen) { if (!optval || optlen != sizeof (int)) { @@ -267,13 +268,12 @@ setopt_gdbm_getflags (GDBM_FILE dbf, void *optval, int optlen) if (!dbf->memory_mapping) flags |= GDBM_NOMMAP; *(int*) optval = flags; } return 0; } -#endif static int setopt_gdbm_getdbname (GDBM_FILE dbf, void *optval, int optlen) { if (!optval || optlen != sizeof (char*)) { @@ -320,14 +320,14 @@ static setopt_handler setopt_handler_tab[] = { [GDBM_GETCOALESCEBLKS] = setopt_gdbm_getcoalesceblks, #if HAVE_MMAP [GDBM_SETMMAP] = setopt_gdbm_setmmap, [GDBM_GETMMAP] = setopt_gdbm_getmmap, [GDBM_SETMAXMAPSIZE] = setopt_gdbm_setmaxmapsize, [GDBM_GETMAXMAPSIZE] = setopt_gdbm_getmaxmapsize, - [GDBM_GETFLAGS] = setopt_gdbm_getflags, #endif + [GDBM_GETFLAGS] = setopt_gdbm_getflags, [GDBM_GETDBNAME] = setopt_gdbm_getdbname, [GDBM_GETBLOCKSIZE] = setopt_gdbm_getblocksize, }; int gdbm_setopt (GDBM_FILE dbf, int optflag, void *optval, int optlen) @@ -119,54 +119,12 @@ _gdbm_internal_remap (GDBM_FILE dbf, size_t size) } dbf->mapped_region = p; return 0; } -/* Grow the disk file of DBF to the SIZE bytes in length. Fill the - newly allocated space with zeros. */ -static int -_gdbm_file_extend (GDBM_FILE dbf, off_t size) -{ - size_t page_size = sysconf (_SC_PAGESIZE); - char *buf; - off_t file_end; - - file_end = lseek (dbf->desc, 0, SEEK_END); - if (!file_end) - { - GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, FALSE); - return -1; - } - size -= file_end; - - if (size < page_size) - page_size = size; - buf = calloc (1, page_size); - if (!buf) - { - GDBM_SET_ERRNO (dbf, GDBM_MALLOC_ERROR, FALSE); - return -1; - } - - while (size) - { - ssize_t n = write (dbf->desc, buf, size < page_size ? size : page_size); - if (n <= 0) - { - GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, FALSE); - break; - } - size -= n; - } - free (buf); - if (size) - return -1; - return 0; -} - # define _REMAP_DEFAULT 0 # define _REMAP_EXTEND 1 # define _REMAP_END 2 /* Remap the GDBM file so that its mapped region ends on SIZEth byte. If the file is opened with write permissions, FLAG controls how diff --git a/src/proto.h b/src/proto.h index 563505f..3fb990c 100644 --- a/src/proto.h +++ b/src/proto.h @@ -65,12 +65,13 @@ int _gdbm_mapped_sync (GDBM_FILE); void _gdbm_unlock_file (GDBM_FILE); int _gdbm_lock_file (GDBM_FILE); /* From fullio.c */ int _gdbm_full_read (GDBM_FILE, void *, size_t); int _gdbm_full_write (GDBM_FILE, void *, size_t); +int _gdbm_file_extend (GDBM_FILE dbf, off_t size); /* From base64.c */ int _gdbm_base64_encode (const unsigned char *input, size_t input_len, unsigned char **output, size_t *output_size, size_t *outbytes); int _gdbm_base64_decode (const unsigned char *input, size_t input_len, diff --git a/src/update.c b/src/update.c index e3ee717..d10d31f 100644 --- a/src/update.c +++ b/src/update.c @@ -119,12 +119,14 @@ _gdbm_end_update (GDBM_FILE dbf) /* Final write of the header. */ if (dbf->header_changed) { if (write_header (dbf)) return -1; + if (_gdbm_file_extend (dbf, dbf->header->next_block)) + return -1; dbf->header_changed = FALSE; } return 0; } |