version 1.1.1.3, 2016/11/01 09:54:32
|
version 1.1.1.4, 2021/03/17 00:32:36
|
Line 3
|
Line 3
|
* |
* |
* Copyright (C) 1998 Andrew Tridgell |
* Copyright (C) 1998 Andrew Tridgell |
* Copyright (C) 2002 Martin Pool |
* Copyright (C) 2002 Martin Pool |
* Copyright (C) 2004-2015 Wayne Davison | * Copyright (C) 2004-2020 Wayne Davison |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
Line 26
|
Line 26
|
#define ENODATA EAGAIN |
#define ENODATA EAGAIN |
#endif |
#endif |
|
|
/* We want all reads to be aligned on 1K boundries. */ | /* We want all reads to be aligned on 1K boundaries. */ |
#define ALIGN_BOUNDRY 1024 | #define ALIGN_BOUNDARY 1024 |
/* How far past the boundary is an offset? */ |
/* How far past the boundary is an offset? */ |
#define ALIGNED_OVERSHOOT(oft) ((oft) & (ALIGN_BOUNDRY-1)) | #define ALIGNED_OVERSHOOT(oft) ((oft) & (ALIGN_BOUNDARY-1)) |
/* Round up a length to the next boundary */ |
/* Round up a length to the next boundary */ |
#define ALIGNED_LENGTH(len) ((((len) - 1) | (ALIGN_BOUNDRY-1)) + 1) | #define ALIGNED_LENGTH(len) ((((len) - 1) | (ALIGN_BOUNDARY-1)) + 1) |
|
|
extern int sparse_files; |
extern int sparse_files; |
|
extern int sparse_files_block_size; |
|
|
|
OFF_T preallocated_len = 0; |
|
|
static OFF_T sparse_seek = 0; |
static OFF_T sparse_seek = 0; |
|
static OFF_T sparse_past_write = 0; |
|
|
int sparse_end(int f, OFF_T size) |
int sparse_end(int f, OFF_T size) |
{ |
{ |
int ret; |
int ret; |
|
|
|
sparse_past_write = 0; |
|
|
if (!sparse_seek) |
if (!sparse_seek) |
return 0; |
return 0; |
|
|
Line 63 int sparse_end(int f, OFF_T size)
|
Line 69 int sparse_end(int f, OFF_T size)
|
return ret; |
return ret; |
} |
} |
|
|
| /* Note that the offset is just the caller letting us know where |
static int write_sparse(int f, char *buf, int len) | * the current file position is in the file. The use_seek arg tells |
| * us that we should seek over matching data instead of writing it. */ |
| static int write_sparse(int f, int use_seek, OFF_T offset, const char *buf, int len) |
{ |
{ |
int l1 = 0, l2 = 0; |
int l1 = 0, l2 = 0; |
int ret; |
int ret; |
Line 77 static int write_sparse(int f, char *buf, int len)
|
Line 85 static int write_sparse(int f, char *buf, int len)
|
if (l1 == len) |
if (l1 == len) |
return len; |
return len; |
|
|
if (sparse_seek) | if (sparse_seek) { |
do_lseek(f, sparse_seek, SEEK_CUR); | if (sparse_past_write >= preallocated_len) { |
| if (do_lseek(f, sparse_seek, SEEK_CUR) < 0) |
| return -1; |
| } else if (do_punch_hole(f, sparse_past_write, sparse_seek) < 0) { |
| sparse_seek = 0; |
| return -1; |
| } |
| } |
sparse_seek = l2; |
sparse_seek = l2; |
|
sparse_past_write = offset + len - l2; |
|
|
|
if (use_seek) { |
|
/* The in-place data already matches. */ |
|
if (do_lseek(f, len - (l1+l2), SEEK_CUR) < 0) |
|
return -1; |
|
return len; |
|
} |
|
|
while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) { |
while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) { |
if (ret < 0 && errno == EINTR) |
if (ret < 0 && errno == EINTR) |
continue; |
continue; |
Line 96 static int write_sparse(int f, char *buf, int len)
|
Line 119 static int write_sparse(int f, char *buf, int len)
|
return len; |
return len; |
} |
} |
|
|
|
|
static char *wf_writeBuf; |
static char *wf_writeBuf; |
static size_t wf_writeBufSize; |
static size_t wf_writeBufSize; |
static size_t wf_writeBufCnt; |
static size_t wf_writeBufCnt; |
Line 118 int flush_write_file(int f)
|
Line 140 int flush_write_file(int f)
|
return ret; |
return ret; |
} |
} |
|
|
| /* write_file does not allow incomplete writes. It loops internally |
/* | * until len bytes are written or errno is set. Note that use_seek and |
* write_file does not allow incomplete writes. It loops internally | * offset are only used in sparse processing (see write_sparse()). */ |
* until len bytes are written or errno is set. | int write_file(int f, int use_seek, OFF_T offset, const char *buf, int len) |
*/ | |
int write_file(int f, char *buf, int len) | |
{ |
{ |
int ret = 0; |
int ret = 0; |
|
|
while (len > 0) { |
while (len > 0) { |
int r1; |
int r1; |
if (sparse_files > 0) { |
if (sparse_files > 0) { |
int len1 = MIN(len, SPARSE_WRITE_SIZE); | int len1 = MIN(len, sparse_files_block_size); |
r1 = write_sparse(f, buf, len1); | r1 = write_sparse(f, use_seek, offset, buf, len1); |
| offset += r1; |
} else { |
} else { |
if (!wf_writeBuf) { |
if (!wf_writeBuf) { |
wf_writeBufSize = WRITE_SIZE * 8; |
wf_writeBufSize = WRITE_SIZE * 8; |
wf_writeBufCnt = 0; |
wf_writeBufCnt = 0; |
wf_writeBuf = new_array(char, wf_writeBufSize); |
wf_writeBuf = new_array(char, wf_writeBufSize); |
if (!wf_writeBuf) |
|
out_of_memory("write_file"); |
|
} |
} |
r1 = (int)MIN((size_t)len, wf_writeBufSize - wf_writeBufCnt); |
r1 = (int)MIN((size_t)len, wf_writeBufSize - wf_writeBufCnt); |
if (r1) { |
if (r1) { |
Line 164 int write_file(int f, char *buf, int len)
|
Line 183 int write_file(int f, char *buf, int len)
|
return ret; |
return ret; |
} |
} |
|
|
|
/* An in-place update found identical data at an identical location. We either |
|
* just seek past it, or (for an in-place sparse update), we give the data to |
|
* the sparse processor with the use_seek flag set. */ |
|
int skip_matched(int fd, OFF_T offset, const char *buf, int len) |
|
{ |
|
OFF_T pos; |
|
|
|
if (sparse_files > 0) { |
|
if (write_file(fd, 1, offset, buf, len) != len) |
|
return -1; |
|
return 0; |
|
} |
|
|
|
if (flush_write_file(fd) < 0) |
|
return -1; |
|
|
|
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset + len) { |
|
rsyserr(FERROR_XFER, errno, "lseek returned %s, not %s", |
|
big_num(pos), big_num(offset)); |
|
return -1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
/* This provides functionality somewhat similar to mmap() but using read(). |
/* This provides functionality somewhat similar to mmap() but using read(). |
* It gives sliding window access to a file. mmap() is not used because of |
* It gives sliding window access to a file. mmap() is not used because of |
* the possibility of another program (such as a mailer) truncating the |
* the possibility of another program (such as a mailer) truncating the |
Line 173 struct map_struct *map_file(int fd, OFF_T len, int32 r
|
Line 216 struct map_struct *map_file(int fd, OFF_T len, int32 r
|
{ |
{ |
struct map_struct *map; |
struct map_struct *map; |
|
|
if (!(map = new0(struct map_struct))) | map = new0(struct map_struct); |
out_of_memory("map_file"); | |
|
|
if (blk_size && (read_size % blk_size)) |
if (blk_size && (read_size % blk_size)) |
read_size += blk_size - (read_size % blk_size); |
read_size += blk_size - (read_size % blk_size); |
Line 217 char *map_ptr(struct map_struct *map, OFF_T offset, in
|
Line 259 char *map_ptr(struct map_struct *map, OFF_T offset, in
|
/* make sure we have allocated enough memory for the window */ |
/* make sure we have allocated enough memory for the window */ |
if (window_size > map->p_size) { |
if (window_size > map->p_size) { |
map->p = realloc_array(map->p, char, window_size); |
map->p = realloc_array(map->p, char, window_size); |
if (!map->p) |
|
out_of_memory("map_ptr"); |
|
map->p_size = window_size; |
map->p_size = window_size; |
} |
} |
|
|
Line 271 char *map_ptr(struct map_struct *map, OFF_T offset, in
|
Line 311 char *map_ptr(struct map_struct *map, OFF_T offset, in
|
return map->p + align_fudge; |
return map->p + align_fudge; |
} |
} |
|
|
|
|
int unmap_file(struct map_struct *map) |
int unmap_file(struct map_struct *map) |
{ |
{ |
int ret; |
int ret; |
Line 281 int unmap_file(struct map_struct *map)
|
Line 320 int unmap_file(struct map_struct *map)
|
map->p = NULL; |
map->p = NULL; |
} |
} |
ret = map->status; |
ret = map->status; |
memset(map, 0, sizeof map[0]); | #if 0 /* I don't think we really need this. */ |
| force_memzero(map, sizeof map[0]); |
| #endif |
free(map); |
free(map); |
|
|
return ret; |
return ret; |