diff options
Diffstat (limited to 'src/mmap.c')
-rw-r--r-- | src/mmap.c | 22 |
1 files changed, 20 insertions, 2 deletions
@@ -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) |