summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org>2017-12-21 07:19:41 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2017-12-21 07:26:54 (GMT)
commit2e8a5e0be7b2db179018c10248a6cc64f9db3314 (patch) (side-by-side diff)
tree6c36d26a1b6c6e668628683978baa2acea3ad3ba /src
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') (more/less context) (ignore whitespace changes)
-rw-r--r--src/gdbmload.c13
-rw-r--r--src/gdbmopen.c20
-rw-r--r--src/mmap.c59
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
@@ -295,7 +295,6 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask)
int meta_flags = 0;
const char *p;
char *end;
- int rc = 0;
if (!(meta_mask & GDBM_META_MASK_OWNER))
{
@@ -366,7 +365,11 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask)
if ((meta_flags & (META_UID|META_GID)) != (META_UID|META_GID))
{
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))
owner_uid = st.st_uid;
if (!(meta_flags & META_GID))
@@ -375,16 +378,16 @@ _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask)
if (fchown (fd, owner_uid, owner_gid))
{
GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE);
- rc = 1;
+ return 1;
}
}
if ((meta_flags & META_MODE) && fchmod (fd, mode))
{
GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE);
- rc = 1;
+ return 1;
}
}
- return rc;
+ return 0;
}
int
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 80474a6..cb73669 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -71,7 +71,7 @@ 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)
{
if (flags & GDBM_CLOERROR)
@@ -171,7 +171,15 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
if ((flags & GDBM_OPENMASK) == GDBM_NEWDB && file_stat.st_size != 0)
{
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;
+ }
}
/* Decide if this is a new file or an old file. */
@@ -208,7 +216,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
/* Get space for the file header. It will be written to disk, so
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)
{
if (!(flags & GDBM_CLOERROR))
@@ -241,7 +249,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
(dbf->header->block_size - sizeof (hash_bucket))
/ sizeof (bucket_element) + 1;
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)
{
if (!(flags & GDBM_CLOERROR))
@@ -356,7 +364,7 @@ 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)
{
if (!(flags & GDBM_CLOERROR))
@@ -379,7 +387,7 @@ 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)
{
if (!(flags & GDBM_CLOERROR))
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.