aboutsummaryrefslogtreecommitdiff
path: root/src/mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mmap.c')
-rw-r--r--src/mmap.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/mmap.c b/src/mmap.c
index 114d8b2..24ede29 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -35,26 +35,33 @@
/* Translate current offset in the mapped region into the absolute position */
# define _GDBM_MMAPPED_POS(dbf) ((dbf)->mapped_off + (dbf)->mapped_pos)
/* Return true if the absolute offset OFF lies within the currentlty mmapped
region */
# define _GDBM_IN_MAPPED_REGION_P(dbf, off) \
((off) >= (dbf)->mapped_off \
&& ((off) - (dbf)->mapped_off) < (dbf)->mapped_size)
/* Return true if the current region needs to be remapped */
# define _GDBM_NEED_REMAP(dbf) \
(!(dbf)->mapped_region || (dbf)->mapped_pos == (dbf)->mapped_size)
/* Return the sum of the currently mapped size and DELTA */
-# define SUM_FILE_SIZE(dbf, delta) \
- ((dbf)->mapped_off + (dbf)->mapped_size + (delta))
+static inline off_t
+SUM_FILE_SIZE (GDBM_FILE dbf, off_t delta)
+{
+ if (delta >= 0
+ && off_t_sum_ok (dbf->mapped_off, dbf->mapped_size)
+ && off_t_sum_ok (dbf->mapped_off + dbf->mapped_size, delta))
+ return dbf->mapped_off + dbf->mapped_size + delta;
+ return -1;
+}
/* Store the size of the GDBM file DBF in *PSIZE.
Return 0 on success and -1 on failure. */
int
_gdbm_file_size (GDBM_FILE dbf, off_t *psize)
{
struct stat sb;
if (fstat (dbf->desc, &sb))
{
GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE);
return -1;
}
@@ -173,24 +180,35 @@ _gdbm_file_extend (GDBM_FILE dbf, off_t size)
truncated to the actual file size.
The upper bound obtained that way is used as a *hint* to select
the actual size of the mapped region. which can never exceed
dbf->mapped_size_max.
The function returns 0 on success, -1 on failure. */
int
_gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag)
{
off_t file_size, pos;
+ if (size < 0)
+ {
+ errno = EINVAL;
+ GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, TRUE);
+ return -1;
+ }
+
+ if (size < dbf->mapped_size)
+ /* Nothing to do */
+ return 0;
+
if (_gdbm_file_size (dbf, &file_size))
{
SAVE_ERRNO (_gdbm_mapped_unmap (dbf));
return -1;
}
if (flag == _REMAP_END && size < file_size)
size = file_size;
if (dbf->read_write)
{
if (size > file_size)

Return to:

Send suggestions and report system problems to the System administrator.