aboutsummaryrefslogtreecommitdiff
path: root/src/mmap.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2017-12-21 09:19:41 +0200
committerSergey Poznyakoff <gray@gnu.org>2017-12-21 09:26:54 +0200
commit2e8a5e0be7b2db179018c10248a6cc64f9db3314 (patch)
tree6c36d26a1b6c6e668628683978baa2acea3ad3ba /src/mmap.c
parentc175231e2781abd17eabf412cfb597654a076c7b (diff)
downloadgdbm-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/mmap.c')
-rw-r--r--src/mmap.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/src/mmap.c b/src/mmap.c
index 27f0e75..69bb58b 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -54,7 +54,10 @@ _gdbm_file_size (GDBM_FILE dbf, off_t *psize)
{
struct stat sb;
if (fstat (dbf->desc, &sb))
- return -1;
+ {
+ GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE);
+ return -1;
+ }
*psize = sb.st_size;
return 0;
}
@@ -112,6 +115,48 @@ _gdbm_internal_remap (GDBM_FILE dbf, size_t size)
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
@@ -140,7 +185,6 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag)
if (_gdbm_file_size (dbf, &file_size))
{
SAVE_ERRNO (_gdbm_mapped_unmap (dbf));
- GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE);
return -1;
}
@@ -153,12 +197,10 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag)
{
if (flag != _REMAP_DEFAULT)
{
- 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;
}
else
@@ -334,10 +376,7 @@ _gdbm_mapped_lseek (GDBM_FILE dbf, off_t offset, int whence)
{
off_t file_size;
if (_gdbm_file_size (dbf, &file_size))
- {
- GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE);
- return -1;
- }
+ return -1;
needle = file_size - offset;
break;
}

Return to:

Send suggestions and report system problems to the System administrator.