--- embedaddon/rsync/fileio.c 2016/11/01 09:54:32 1.1.1.3 +++ embedaddon/rsync/fileio.c 2021/03/17 00:32:36 1.1.1.4 @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Andrew Tridgell * 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 * it under the terms of the GNU General Public License as published by @@ -26,21 +26,27 @@ #define ENODATA EAGAIN #endif -/* We want all reads to be aligned on 1K boundries. */ -#define ALIGN_BOUNDRY 1024 +/* We want all reads to be aligned on 1K boundaries. */ +#define ALIGN_BOUNDARY 1024 /* 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 */ -#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_block_size; +OFF_T preallocated_len = 0; + static OFF_T sparse_seek = 0; +static OFF_T sparse_past_write = 0; int sparse_end(int f, OFF_T size) { int ret; + sparse_past_write = 0; + if (!sparse_seek) return 0; @@ -63,8 +69,10 @@ int sparse_end(int f, OFF_T size) return ret; } - -static int write_sparse(int f, char *buf, int len) +/* Note that the offset is just the caller letting us know where + * 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 ret; @@ -77,10 +85,25 @@ static int write_sparse(int f, char *buf, int len) if (l1 == len) return len; - if (sparse_seek) - do_lseek(f, sparse_seek, SEEK_CUR); + if (sparse_seek) { + 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_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) { if (ret < 0 && errno == EINTR) continue; @@ -96,7 +119,6 @@ static int write_sparse(int f, char *buf, int len) return len; } - static char *wf_writeBuf; static size_t wf_writeBufSize; static size_t wf_writeBufCnt; @@ -118,27 +140,24 @@ int flush_write_file(int f) return ret; } - -/* - * write_file does not allow incomplete writes. It loops internally - * until len bytes are written or errno is set. - */ -int write_file(int f, char *buf, int len) +/* write_file does not allow incomplete writes. It loops internally + * until len bytes are written or errno is set. Note that use_seek and + * offset are only used in sparse processing (see write_sparse()). */ +int write_file(int f, int use_seek, OFF_T offset, const char *buf, int len) { int ret = 0; while (len > 0) { int r1; if (sparse_files > 0) { - int len1 = MIN(len, SPARSE_WRITE_SIZE); - r1 = write_sparse(f, buf, len1); + int len1 = MIN(len, sparse_files_block_size); + r1 = write_sparse(f, use_seek, offset, buf, len1); + offset += r1; } else { if (!wf_writeBuf) { wf_writeBufSize = WRITE_SIZE * 8; wf_writeBufCnt = 0; 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); if (r1) { @@ -164,7 +183,31 @@ int write_file(int f, char *buf, int len) 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(). * 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 @@ -173,8 +216,7 @@ struct map_struct *map_file(int fd, OFF_T len, int32 r { struct map_struct *map; - if (!(map = new0(struct map_struct))) - out_of_memory("map_file"); + map = new0(struct map_struct); if (blk_size && (read_size % blk_size)) read_size += blk_size - (read_size % blk_size); @@ -217,8 +259,6 @@ char *map_ptr(struct map_struct *map, OFF_T offset, in /* make sure we have allocated enough memory for the window */ if (window_size > map->p_size) { map->p = realloc_array(map->p, char, window_size); - if (!map->p) - out_of_memory("map_ptr"); map->p_size = window_size; } @@ -271,7 +311,6 @@ char *map_ptr(struct map_struct *map, OFF_T offset, in return map->p + align_fudge; } - int unmap_file(struct map_struct *map) { int ret; @@ -281,7 +320,9 @@ int unmap_file(struct map_struct *map) map->p = NULL; } 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); return ret;