1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
|
commit f3873b3d88b61167b106e7b9227a20147f8f6197
Author: Wayne Davison <wayned@samba.org>
Date: Mon Oct 10 11:49:50 2016 -0700
Support --sparse combined with --preallocate or --inplace.
The new code tries to punch holes in the destination file using newer
Linux fallocate features. It also supports a --whole-file + --sparse +
--inplace copy on any filesystem by truncating the destination file.
diff --git a/configure.ac b/configure.ac
index b5e4049..e01e124 100644
--- a/configure.ac
+++ b/configure.ac
@@ -614,6 +614,36 @@ if test x"$rsync_cv_have_fallocate" = x"yes"; then
AC_DEFINE(HAVE_FALLOCATE, 1, [Define to 1 if you have the fallocate function and it compiles and links without error])
fi
+AC_MSG_CHECKING([for FALLOC_FL_PUNCH_HOLE])
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
+ #define _GNU_SOURCE 1
+ #include <linux/falloc.h>
+ #ifndef FALLOC_FL_PUNCH_HOLE
+ #error FALLOC_FL_PUNCH_HOLE is missing
+ #endif
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_FALLOC_FL_PUNCH_HOLE], [1], [Define if FALLOC_FL_PUNCH_HOLE is available.])
+ ], [
+ AC_MSG_RESULT([no])
+ ]
+)
+
+AC_MSG_CHECKING([for FALLOC_FL_ZERO_RANGE])
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
+ #define _GNU_SOURCE 1
+ #include <linux/falloc.h>
+ #ifndef FALLOC_FL_ZERO_RANGE
+ #error FALLOC_FL_ZERO_RANGE is missing
+ #endif
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_FALLOC_FL_ZERO_RANGE], [1], [Define if FALLOC_FL_ZERO_RANGE is available.])
+ ], [
+ AC_MSG_RESULT([no])
+ ]
+)
+
AC_CACHE_CHECK([for SYS_fallocate],rsync_cv_have_sys_fallocate,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/syscall.h>
#include <sys/types.h>]], [[syscall(SYS_fallocate, 0, 0, (loff_t)0, (loff_t)0);]])],[rsync_cv_have_sys_fallocate=yes],[rsync_cv_have_sys_fallocate=no])])
diff --git a/fileio.c b/fileio.c
index 70e079d..1e8a562 100644
--- a/fileio.c
+++ b/fileio.c
@@ -35,7 +35,10 @@
extern int sparse_files;
+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)
{
@@ -63,8 +66,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,9 +82,24 @@ 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)
@@ -96,7 +116,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,12 +137,10 @@ 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;
@@ -131,7 +148,8 @@ int write_file(int f, char *buf, int len)
int r1;
if (sparse_files > 0) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
- r1 = write_sparse(f, buf, len1);
+ r1 = write_sparse(f, use_seek, offset, buf, len1);
+ offset += r1;
} else {
if (!wf_writeBuf) {
wf_writeBufSize = WRITE_SIZE * 8;
@@ -164,6 +182,30 @@ 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
@@ -271,7 +313,6 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
return map->p + align_fudge;
}
-
int unmap_file(struct map_struct *map)
{
int ret;
diff --git a/options.c b/options.c
index 308443b..6ba13b7 100644
--- a/options.c
+++ b/options.c
@@ -714,7 +714,7 @@ void usage(enum logcode F)
#ifdef SUPPORT_XATTRS
rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
#endif
- rprintf(F," -S, --sparse handle sparse files efficiently\n");
+ rprintf(F," -S, --sparse turn sequences of nulls into sparse blocks\n");
#ifdef SUPPORT_PREALLOCATION
rprintf(F," --preallocate allocate dest files before writing them\n");
#else
@@ -2237,14 +2237,6 @@ int parse_arguments(int *argc_p, const char ***argv_p)
bwlimit_writemax = 512;
}
- if (sparse_files && inplace) {
- /* Note: we don't check for this below, because --append is
- * OK with --sparse (as long as redos are handled right). */
- snprintf(err_buf, sizeof err_buf,
- "--sparse cannot be used with --inplace\n");
- return 0;
- }
-
if (append_mode) {
if (whole_file > 0) {
snprintf(err_buf, sizeof err_buf,
diff --git a/receiver.c b/receiver.c
index f9b97dd..bed5328 100644
--- a/receiver.c
+++ b/receiver.c
@@ -49,6 +49,7 @@ extern int sparse_files;
extern int preallocate_files;
extern int keep_partial;
extern int checksum_seed;
+extern int whole_file;
extern int inplace;
extern int allowed_lull;
extern int delay_updates;
@@ -61,6 +62,9 @@ extern char *basis_dir[MAX_BASIS_DIRS+1];
extern char sender_file_sum[MAX_DIGEST_LEN];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern filter_rule_list daemon_filter_list;
+#ifdef SUPPORT_PREALLOCATION
+extern OFF_T preallocated_len;
+#endif
static struct bitbag *delayed_bits = NULL;
static int phase = 0, redoing = 0;
@@ -241,22 +245,25 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
char *data;
int32 i;
char *map = NULL;
-#ifdef SUPPORT_PREALLOCATION
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
- OFF_T preallocated_len = 0;
-#endif
+#ifdef SUPPORT_PREALLOCATION
if (preallocate_files && fd != -1 && total_size > 0 && (!inplace || total_size > size_r)) {
/* Try to preallocate enough space for file's eventual length. Can
* reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
- if (do_fallocate(fd, 0, total_size) == 0) {
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
- preallocated_len = total_size;
-#endif
- } else
+ if ((preallocated_len = do_fallocate(fd, 0, total_size)) < 0)
rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(fname));
- }
+ } else
+#endif
+ if (inplace) {
+#ifdef HAVE_FTRUNCATE
+ /* The most compatible way to create a sparse file is to start with no length. */
+ if (sparse_files > 0 && whole_file && fd >= 0 && do_ftruncate(fd, 0) == 0)
+ preallocated_len = 0;
+ else
#endif
+ preallocated_len = size_r;
+ } else
+ preallocated_len = 0;
read_sum_head(f_in, &sum);
@@ -318,7 +325,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_update(data, i);
- if (fd != -1 && write_file(fd,data,i) != i)
+ if (fd != -1 && write_file(fd, 0, offset, data, i) != i)
goto report_write_error;
offset += i;
continue;
@@ -348,37 +355,33 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
if (updating_basis_or_equiv) {
if (offset == offset2 && fd != -1) {
- OFF_T pos;
- if (flush_write_file(fd) < 0)
+ if (skip_matched(fd, offset, map, len) < 0)
goto report_write_error;
offset += len;
- if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
- rsyserr(FERROR_XFER, errno,
- "lseek of %s returned %s, not %s",
- full_fname(fname),
- big_num(pos), big_num(offset));
- exit_cleanup(RERR_FILEIO);
- }
continue;
}
}
- if (fd != -1 && map && write_file(fd, map, len) != (int)len)
+ if (fd != -1 && map && write_file(fd, 0, offset, map, len) != (int)len)
goto report_write_error;
offset += len;
}
- if (flush_write_file(fd) < 0)
- goto report_write_error;
+ if (fd != -1 && offset > 0) {
+ if (sparse_files > 0) {
+ if (sparse_end(fd, offset) != 0)
+ goto report_write_error;
+ } else if (flush_write_file(fd) < 0) {
+ report_write_error:
+ rsyserr(FERROR_XFER, errno, "write failed on %s", full_fname(fname));
+ exit_cleanup(RERR_FILEIO);
+ }
+ }
#ifdef HAVE_FTRUNCATE
/* inplace: New data could be shorter than old data.
* preallocate_files: total_size could have been an overestimate.
* Cut off any extra preallocated zeros from dest file. */
- if ((inplace
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
- || preallocated_len > offset
-#endif
- ) && fd != -1 && do_ftruncate(fd, offset) < 0) {
+ if ((inplace || preallocated_len > offset) && fd != -1 && do_ftruncate(fd, offset) < 0) {
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
full_fname(fname));
}
@@ -387,13 +390,6 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
if (INFO_GTE(PROGRESS, 1))
end_progress(total_size);
- if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
- report_write_error:
- rsyserr(FERROR_XFER, errno, "write failed on %s",
- full_fname(fname));
- exit_cleanup(RERR_FILEIO);
- }
-
checksum_len = sum_end(file_sum1);
if (mapbuf)
diff --git a/rsync.yo b/rsync.yo
index bfe43b9..d1e6fdf 100644
--- a/rsync.yo
+++ b/rsync.yo
@@ -376,7 +376,7 @@ to the detailed description below for a complete description. verb(
-J, --omit-link-times omit symlinks from --times
--super receiver attempts super-user activities
--fake-super store/recover privileged attrs using xattrs
- -S, --sparse handle sparse files efficiently
+ -S, --sparse turn sequences of nulls into sparse blocks
--preallocate allocate dest files before writing
-n, --dry-run perform a trial run with no changes made
-W, --whole-file copy files whole (w/o delta-xfer algorithm)
@@ -873,9 +873,7 @@ the same or longer than the size on the sender, the file is skipped. This
does not interfere with the updating of a file's non-content attributes
(e.g. permissions, ownership, etc.) when the file does not need to be
transferred, nor does it affect the updating of any non-regular files.
-Implies bf(--inplace),
-but does not conflict with bf(--sparse) (since it is always extending a
-file's length).
+Implies bf(--inplace).
The use of bf(--append) can be dangerous if you aren't 100% sure that the files
that are longer have only grown by the appending of data onto the end. You
@@ -1252,20 +1250,30 @@ This option is overridden by both bf(--super) and bf(--no-super).
See also the "fake super" setting in the daemon's rsyncd.conf file.
dit(bf(-S, --sparse)) Try to handle sparse files efficiently so they take
-up less space on the destination. Conflicts with bf(--inplace) because it's
-not possible to overwrite data in a sparse fashion.
+up less space on the destination. If combined with bf(--inplace) the
+file created might not end up with sparse blocks with some combinations
+of kernel version and/or filesystem type. If bf(--whole-file) is in
+effect (e.g. for a local copy) then it will always work because rsync
+truncates the file prior to writing out the updated version.
+
+Note that versions of rsync older than 3.1.3 will reject the combination of
+bf(--sparse) and bf(--inplace).
dit(bf(--preallocate)) This tells the receiver to allocate each destination
-file to its eventual size before writing data to the file. Rsync will only use
-the real filesystem-level preallocation support provided by Linux's
+file to its eventual size before writing data to the file. Rsync will only
+use the real filesystem-level preallocation support provided by Linux's
bf(fallocate)(2) system call or Cygwin's bf(posix_fallocate)(3), not the slow
-glibc implementation that writes a zero byte into each block.
+glibc implementation that writes a null byte into each block.
Without this option, larger files may not be entirely contiguous on the
filesystem, but with this option rsync will probably copy more slowly. If the
destination is not an extent-supporting filesystem (such as ext4, xfs, NTFS,
etc.), this option may have no positive effect at all.
+If combined with bf(--sparse), the file will only have sparse blocks (as
+opposed to allocated sequences of null bytes) if the kernel version and
+filesystem type support creating holes in the allocated data.
+
dit(bf(-n, --dry-run)) This makes rsync perform a trial run that doesn't
make any changes (and produces mostly the same output as a real run). It
is most commonly used in combination with the bf(-v, --verbose) and/or
diff --git a/syscall.c b/syscall.c
index ecca2f1..fa53b63 100644
--- a/syscall.c
+++ b/syscall.c
@@ -38,6 +38,8 @@ extern int am_root;
extern int am_sender;
extern int read_only;
extern int list_only;
+extern int inplace;
+extern int preallocate_files;
extern int preserve_perms;
extern int preserve_executability;
@@ -423,27 +425,80 @@ int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
#endif
#ifdef SUPPORT_PREALLOCATION
-int do_fallocate(int fd, OFF_T offset, OFF_T length)
-{
#ifdef FALLOC_FL_KEEP_SIZE
#define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
#else
#define DO_FALLOC_OPTIONS 0
#endif
+
+OFF_T do_fallocate(int fd, OFF_T offset, OFF_T length)
+{
+ int opts = inplace || preallocate_files ? 0 : DO_FALLOC_OPTIONS;
+ int ret;
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF_RO_OR_LO;
+ if (length & 1) /* make the length not match the desired length */
+ length++;
+ else
+ length--;
#if defined HAVE_FALLOCATE
- return fallocate(fd, DO_FALLOC_OPTIONS, offset, length);
+ ret = fallocate(fd, opts, offset, length);
#elif defined HAVE_SYS_FALLOCATE
- return syscall(SYS_fallocate, fd, DO_FALLOC_OPTIONS, (loff_t)offset, (loff_t)length);
+ ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
#elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
- return posix_fallocate(fd, offset, length);
+ ret = posix_fallocate(fd, offset, length);
#else
#error Coding error in SUPPORT_PREALLOCATION logic.
#endif
+ if (ret < 0)
+ return ret;
+ if (opts == 0) {
+ STRUCT_STAT st;
+ if (do_fstat(fd, &st) < 0)
+ return length;
+ return st.st_blocks * 512;
+ }
+ return 0;
}
#endif
+/* Punch a hole at pos for len bytes. The current file position must be at pos and will be
+ * changed to be at pos + len. */
+int do_punch_hole(int fd, UNUSED(OFF_T pos), int len)
+{
+#ifdef HAVE_FALLOCATE
+# ifdef HAVE_FALLOC_FL_PUNCH_HOLE
+ if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, pos, len) == 0) {
+ if (do_lseek(fd, len, SEEK_CUR) != pos + len)
+ return -1;
+ return 0;
+ }
+# endif
+# ifdef HAVE_FALLOC_FL_ZERO_RANGE
+ if (fallocate(fd, FALLOC_FL_ZERO_RANGE, pos, len) == 0) {
+ if (do_lseek(fd, len, SEEK_CUR) != pos + len)
+ return -1;
+ return 0;
+ }
+# endif
+#endif
+ {
+ char zeros[4096];
+ memset(zeros, 0, sizeof zeros);
+ while (len > 0) {
+ int chunk = len > (int)sizeof zeros ? (int)sizeof zeros : len;
+ int wrote = write(fd, zeros, chunk);
+ if (wrote <= 0) {
+ if (wrote < 0 && errno == EINTR)
+ continue;
+ return -1;
+ }
+ len -= wrote;
+ }
+ }
+ return 0;
+}
+
int do_open_nofollow(const char *pathname, int flags)
{
#ifndef O_NOFOLLOW
diff --git a/t_stub.c b/t_stub.c
index 26951a6..fc1ee3b 100644
--- a/t_stub.c
+++ b/t_stub.c
@@ -21,6 +21,7 @@
#include "rsync.h"
+int inplace = 0;
int modify_window = 0;
int preallocate_files = 0;
int protect_args = 0;
diff --git a/tls.c b/tls.c
index 45d1e10..d5a2896 100644
--- a/tls.c
+++ b/tls.c
@@ -51,6 +51,8 @@ int link_owner = 0;
int nsec_times = 0;
int preserve_perms = 0;
int preserve_executability = 0;
+int preallocate_files = 0;
+int inplace = 0;
#ifdef SUPPORT_XATTRS
diff --git a/trimslash.c b/trimslash.c
index 207eaf2..5db6f3e 100644
--- a/trimslash.c
+++ b/trimslash.c
@@ -28,6 +28,8 @@ int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
int preserve_executability = 0;
+int preallocate_files = 0;
+int inplace = 0;
int
main(int argc, char **argv)
diff --git a/util.c b/util.c
index ca38f3e..49c5b71 100644
--- a/util.c
+++ b/util.c
@@ -323,9 +323,7 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
int ifd;
char buf[1024 * 8];
int len; /* Number of bytes read into `buf'. */
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
- OFF_T preallocated_len = 0, offset = 0;
-#endif
+ OFF_T prealloc_len = 0, offset = 0;
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
int save_errno = errno;
@@ -365,11 +363,8 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
if (do_fstat(ifd, &srcst) < 0)
rsyserr(FWARNING, errno, "fstat %s", full_fname(source));
else if (srcst.st_size > 0) {
- if (do_fallocate(ofd, 0, srcst.st_size) == 0) {
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
- preallocated_len = srcst.st_size;
-#endif
- } else
+ prealloc_len = do_fallocate(ofd, 0, srcst.st_size);
+ if (prealloc_len < 0)
rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(dest));
}
}
@@ -384,9 +379,7 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
errno = save_errno;
return -1;
}
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
offset += len;
-#endif
}
if (len < 0) {
@@ -403,15 +396,13 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
full_fname(source));
}
-#ifdef PREALLOCATE_NEEDS_TRUNCATE
/* Source file might have shrunk since we fstatted it.
* Cut off any extra preallocated zeros from dest file. */
- if (offset < preallocated_len && do_ftruncate(ofd, offset) < 0) {
+ if (offset < prealloc_len && do_ftruncate(ofd, offset) < 0) {
/* If we fail to truncate, the dest file may be wrong, so we
* must trigger the "partial transfer" error. */
rsyserr(FERROR_XFER, errno, "ftruncate %s", full_fname(dest));
}
-#endif
if (close(ofd) < 0) {
int save_errno = errno;
|