aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-30 14:04:48 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-05-30 14:04:48 +0300
commit4e819c987988432ef936c6c3e003db6b26463154 (patch)
treefeefee7688cec0df1a66401b9da2204272d8d83f
parentb8d5da4c426b21ca0e56fc1cd6f75b49c0668e95 (diff)
downloadgdbm-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.c46
-rw-r--r--src/gdbmopen.c15
-rw-r--r--src/gdbmsetopt.c4
-rw-r--r--src/mmap.c42
-rw-r--r--src/proto.h1
-rw-r--r--src/update.c2
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)
diff --git a/src/mmap.c b/src/mmap.c
index ba05bd7..008a0f8 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -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;
}

Return to:

Send suggestions and report system problems to the System administrator.