slide the read window in the file */
| 234 | |
| 235 | /* slide the read window in the file */ |
| 236 | char *map_ptr(struct map_struct *map, OFF_T offset, int32 len) |
| 237 | { |
| 238 | OFF_T window_start, read_start; |
| 239 | int32 window_size, read_size, read_offset, align_fudge; |
| 240 | |
| 241 | if (len == 0) |
| 242 | return NULL; |
| 243 | if (len < 0) { |
| 244 | rprintf(FERROR, "invalid len passed to map_ptr: %ld\n", |
| 245 | (long)len); |
| 246 | exit_cleanup(RERR_FILEIO); |
| 247 | } |
| 248 | |
| 249 | /* in most cases the region will already be available */ |
| 250 | if (offset >= map->p_offset && offset+len <= map->p_offset+map->p_len) |
| 251 | return map->p + (offset - map->p_offset); |
| 252 | |
| 253 | /* nope, we are going to have to do a read. Work out our desired window */ |
| 254 | align_fudge = (int32)ALIGNED_OVERSHOOT(offset); |
| 255 | window_start = offset - align_fudge; |
| 256 | window_size = map->def_window_size; |
| 257 | if (window_start + window_size > map->file_size) |
| 258 | window_size = (int32)(map->file_size - window_start); |
| 259 | if (window_size < len + align_fudge) |
| 260 | window_size = ALIGNED_LENGTH(len + align_fudge); |
| 261 | |
| 262 | /* make sure we have allocated enough memory for the window */ |
| 263 | if (window_size > map->p_size) { |
| 264 | map->p = realloc_array(map->p, char, window_size); |
| 265 | map->p_size = window_size; |
| 266 | } |
| 267 | |
| 268 | /* Now try to avoid re-reading any bytes by reusing any bytes from the previous buffer. */ |
| 269 | if (window_start >= map->p_offset && window_start < map->p_offset + map->p_len |
| 270 | && window_start + window_size >= map->p_offset + map->p_len) { |
| 271 | read_start = map->p_offset + map->p_len; |
| 272 | read_offset = (int32)(read_start - window_start); |
| 273 | read_size = window_size - read_offset; |
| 274 | memmove(map->p, map->p + (map->p_len - read_offset), read_offset); |
| 275 | } else { |
| 276 | read_start = window_start; |
| 277 | read_size = window_size; |
| 278 | read_offset = 0; |
| 279 | } |
| 280 | |
| 281 | if (read_size <= 0) { |
| 282 | rprintf(FERROR, "invalid read_size of %ld in map_ptr\n", |
| 283 | (long)read_size); |
| 284 | exit_cleanup(RERR_FILEIO); |
| 285 | } |
| 286 | |
| 287 | if (map->p_fd_offset != read_start) { |
| 288 | OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET); |
| 289 | if (ret != read_start) { |
| 290 | rsyserr(FERROR, errno, "lseek returned %s, not %s", |
| 291 | big_num(ret), big_num(read_start)); |
| 292 | exit_cleanup(RERR_FILEIO); |
| 293 | } |
no test coverage detected