diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2017-12-21 09:19:41 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2017-12-21 09:26:54 +0200 |
commit | 2e8a5e0be7b2db179018c10248a6cc64f9db3314 (patch) | |
tree | 6c36d26a1b6c6e668628683978baa2acea3ad3ba /src | |
parent | c175231e2781abd17eabf412cfb597654a076c7b (diff) | |
download | gdbm-2e8a5e0be7b2db179018c10248a6cc64f9db3314.tar.gz gdbm-2e8a5e0be7b2db179018c10248a6cc64f9db3314.tar.bz2 |
Improve database reproducibility
* src/gdbmopen.c (gdbm_fd_open): Fill allocated memory with 0's
where necessary.
Check return value from fstat.
* src/mmap.c (_gdbm_file_size): Set errno here, instead of delegating
that to the caller.
(_gdbm_file_extend): New function.
(_gdbm_mapped_remap): Call _gdbm_file_extend instead of leaving the
newly allocated space filled with garbage.
* src/gdbmload.c (_set_gdbm_meta_info): Additional error checking.
* NEWS: Update.
Diffstat (limited to 'src')
-rw-r--r-- | src/gdbmload.c | 13 | ||||
-rw-r--r-- | src/gdbmopen.c | 20 | ||||
-rw-r--r-- | src/mmap.c | 59 |
3 files changed, 71 insertions, 21 deletions
diff --git a/src/gdbmload.c b/src/gdbmload.c index f634987..b243d08 100644 --- a/src/gdbmload.c +++ b/src/gdbmload.c @@ -297,3 +297,2 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask) char *end; - int rc = 0; @@ -368,3 +367,7 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask) struct stat st; - fstat (fd, &st); + if (fstat (fd, &st)) + { + GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE); + return 1; + } if (!(meta_flags & META_UID)) @@ -377,3 +380,3 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask) GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE); - rc = 1; + return 1; } @@ -383,6 +386,6 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask) GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE); - rc = 1; + return 1; } } - return rc; + return 0; } diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 80474a6..cb73669 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -73,3 +73,3 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, /* Allocate new info structure. */ - dbf = (GDBM_FILE) malloc (sizeof (*dbf)); + dbf = calloc (1, sizeof (*dbf)); if (dbf == NULL) @@ -173,3 +173,11 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, TRUNCATE (dbf); - fstat (dbf->desc, &file_stat); + if (fstat (dbf->desc, &file_stat)) + { + if (flags & GDBM_CLOERROR) + close (dbf->desc); + free (dbf->name); + free (dbf); + GDBM_SET_ERRNO2 (NULL, GDBM_FILE_STAT_ERROR, FALSE, GDBM_DEBUG_OPEN); + return NULL; + } } @@ -210,3 +218,3 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, make sure there's no garbage in it. */ - dbf->header = (gdbm_file_header *) calloc (1, block_size); + dbf->header = calloc (1, block_size); if (dbf->header == NULL) @@ -243,3 +251,3 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->header->bucket_size = dbf->header->block_size; - dbf->bucket = (hash_bucket *) malloc (dbf->header->bucket_size); + dbf->bucket = calloc (1, dbf->header->bucket_size); if (dbf->bucket == NULL) @@ -358,3 +366,3 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, /* It is a good database, read the entire header. */ - dbf->header = (gdbm_file_header *) malloc (partial_header.block_size); + dbf->header = malloc (partial_header.block_size); if (dbf->header == NULL) @@ -381,3 +389,3 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, /* Allocate space for the hash table directory. */ - dbf->dir = (off_t *) malloc (dbf->header->dir_size); + dbf->dir = malloc (dbf->header->dir_size); if (dbf->dir == NULL) @@ -56,3 +56,6 @@ _gdbm_file_size (GDBM_FILE dbf, off_t *psize) if (fstat (dbf->desc, &sb)) - return -1; + { + GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE); + return -1; + } *psize = sb.st_size; @@ -114,2 +117,44 @@ _gdbm_internal_remap (GDBM_FILE dbf, size_t size) +/* 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 @@ -142,3 +187,2 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag) SAVE_ERRNO (_gdbm_mapped_unmap (dbf)); - GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE); return -1; @@ -155,8 +199,6 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag) { - char c = 0; - if (size < dbf->header->next_block) size = dbf->header->next_block; - lseek (dbf->desc, size - 1, SEEK_SET); - write (dbf->desc, &c, 1); + if (_gdbm_file_extend (dbf, size)) + return -1; file_size = size; @@ -336,6 +378,3 @@ _gdbm_mapped_lseek (GDBM_FILE dbf, off_t offset, int whence) if (_gdbm_file_size (dbf, &file_size)) - { - GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE); - return -1; - } + return -1; needle = file_size - offset; |