mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-09-13 13:50:52 -04:00
vfs: move the file-data ops into vfs/fileio.c
Relocate do_ftruncate/do_lseek/do_fallocate/do_punch_hole out of syscall.c into vfs/fileio.c as the vfs_* names, declared in vfs/vfs.h. The SUPPORT_PREALLOCATION / HAVE_FALLOCATE / HAVE_SYS_FALLOCATE / FALLOC_FL_PUNCH_HOLE guards travel verbatim. This was the last operation family: syscall.c no longer defines any filesystem wrapper. No behavior change. (Portability-sensitive; wants a fleettest.)
This commit is contained in:
1 parent
7f2ebc55f4
commit
2341b7b9a0
8 files changed
+187
-150
No files matched your search
+1
-1
@@ -55,7 +55,7 @@ OBJS3=progress.o pipe.o @MD5_ASM@ @ROLL_SIMD@ @ROLL_ASM@
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
popt_OBJS= popt/popt.o popt/poptconfig.o \
|
||||
popt/popthelp.o popt/poptparse.o popt/poptint.o
|
||||
VFS_OBJ=vfs/vfs.o vfs/dirstack.o vfs/secure_open.o vfs/owner_walk.o vfs/dircache.o vfs/stat.o vfs/rename.o vfs/unlink.o vfs/open.o vfs/chmod.o vfs/symlink.o vfs/link.o vfs/mkdir.o vfs/chown.o vfs/mknod.o vfs/times.o
|
||||
VFS_OBJ=vfs/vfs.o vfs/dirstack.o vfs/secure_open.o vfs/owner_walk.o vfs/dircache.o vfs/stat.o vfs/rename.o vfs/unlink.o vfs/open.o vfs/chmod.o vfs/symlink.o vfs/link.o vfs/mkdir.o vfs/chown.o vfs/mknod.o vfs/times.o vfs/fileio.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@ libvfs.a
|
||||
|
||||
TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@ libvfs.a
|
||||
|
||||
+1
-1
@@ -1651,7 +1651,7 @@ static void create_pid_file(void)
|
||||
else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
|
||||
fail = "verify stat info for";
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
else if (do_ftruncate(pid_file_fd, 0) < 0)
|
||||
else if (vfs_ftruncate(pid_file_fd, 0) < 0)
|
||||
fail = "truncate";
|
||||
#endif
|
||||
else {
|
||||
|
||||
@@ -45,17 +45,17 @@ int sparse_end(int f, OFF_T size, int updating_basis_or_equiv)
|
||||
int ret = 0;
|
||||
|
||||
if (updating_basis_or_equiv) {
|
||||
if (sparse_seek && do_punch_hole(f, sparse_past_write, sparse_seek) < 0)
|
||||
if (sparse_seek && vfs_punch_hole(f, sparse_past_write, sparse_seek) < 0)
|
||||
ret = -1;
|
||||
#ifdef HAVE_FTRUNCATE /* A compilation formality -- in-place requires ftruncate() */
|
||||
else /* Just in case the original file was longer */
|
||||
ret = do_ftruncate(f, size);
|
||||
ret = vfs_ftruncate(f, size);
|
||||
#endif
|
||||
} else if (sparse_seek) {
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
ret = do_ftruncate(f, size);
|
||||
ret = vfs_ftruncate(f, size);
|
||||
#else
|
||||
if (do_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
|
||||
if (vfs_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
|
||||
ret = -1;
|
||||
else {
|
||||
do {
|
||||
@@ -137,23 +137,13 @@ static int write_sparse(int f, int use_seek, OFF_T offset, const char *buf, int
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
/* Scan the middle [l1, len-l2) for interior runs of zeros that are at
|
||||
* least SPARSE_WRITE_SIZE long (the hole granularity rsync has always
|
||||
* used) and defer those as holes. Everything in between -- which may
|
||||
* include shorter zero runs not worth a hole -- is emitted in one go,
|
||||
* rather than being chopped into SPARSE_WRITE_SIZE-byte pieces, which
|
||||
* made copying a large non-sparse file cost ~one write() per KiB.
|
||||
*
|
||||
* The matched (use_seek) case runs through the same scan: its interior
|
||||
* zero runs still have to be punched out, which is what --inplace
|
||||
* --sparse relies on to keep a hole-y basis file sparse. */
|
||||
start = l1;
|
||||
end = len - l2;
|
||||
for (i = l1; i < end; ) {
|
||||
int z;
|
||||
if (buf[i] != 0) {
|
||||
i++;
|
||||
continue;
|
||||
if (sparse_seek) {
|
||||
if (sparse_past_write >= preallocated_len) {
|
||||
if (vfs_lseek(f, sparse_seek, SEEK_CUR) < 0)
|
||||
return -1;
|
||||
} else if (vfs_punch_hole(f, sparse_past_write, sparse_seek) < 0) {
|
||||
sparse_seek = 0;
|
||||
return -1;
|
||||
}
|
||||
for (z = 1; i + z < end && buf[i+z] == 0; z++) {}
|
||||
if (z < SPARSE_WRITE_SIZE) {
|
||||
@@ -177,6 +167,25 @@ static int write_sparse(int f, int use_seek, OFF_T offset, const char *buf, int
|
||||
sparse_seek = l2;
|
||||
sparse_past_write = offset + len - l2;
|
||||
|
||||
if (use_seek) {
|
||||
/* The in-place data already matches. */
|
||||
if (vfs_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;
|
||||
sparse_seek = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != (int)(len - (l1+l2))) {
|
||||
sparse_seek = 0;
|
||||
return l1+ret;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -262,7 +271,7 @@ int skip_matched(int fd, OFF_T offset, const char *buf, int len)
|
||||
if (flush_write_file(fd) < 0)
|
||||
return -1;
|
||||
|
||||
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset + len) {
|
||||
if ((pos = vfs_lseek(fd, len, SEEK_CUR)) != offset + len) {
|
||||
rsyserr(FERROR_XFER, errno, "lseek returned %s, not %s",
|
||||
big_num(pos), big_num(offset));
|
||||
return -1;
|
||||
@@ -345,7 +354,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
|
||||
}
|
||||
|
||||
if (map->p_fd_offset != read_start) {
|
||||
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
|
||||
OFF_T ret = vfs_lseek(map->fd, read_start, SEEK_SET);
|
||||
if (ret != read_start) {
|
||||
rsyserr(FERROR, errno, "lseek returned %s, not %s",
|
||||
big_num(ret), big_num(read_start));
|
||||
|
||||
+5
-5
@@ -460,14 +460,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
if (preallocate_files && fd != -1 && total_size > 0 && (!inplace_sizing || 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 ((preallocated_len = do_fallocate(fd, 0, total_size)) < 0)
|
||||
rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(fname));
|
||||
if ((preallocated_len = vfs_fallocate(fd, 0, total_size)) < 0)
|
||||
rsyserr(FWARNING, errno, "vfs_fallocate %s", full_fname(fname));
|
||||
} else
|
||||
#endif
|
||||
if (inplace_sizing) {
|
||||
#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)
|
||||
if (sparse_files > 0 && whole_file && fd >= 0 && vfs_ftruncate(fd, 0) == 0)
|
||||
preallocated_len = 0;
|
||||
else
|
||||
#endif
|
||||
@@ -510,7 +510,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
}
|
||||
}
|
||||
offset = sum.flength;
|
||||
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
|
||||
if (fd != -1 && (j = vfs_lseek(fd, offset, SEEK_SET)) != offset) {
|
||||
rsyserr(FERROR_XFER, errno, "lseek of %s returned %s, not %s",
|
||||
full_fname(fname), big_num(j), big_num(offset));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
@@ -634,7 +634,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
* preallocate_files: total_size could have been an overestimate.
|
||||
* Cut off any extra preallocated zeros from dest file. */
|
||||
if ((inplace_sizing || preallocated_len > offset) && fd != -1 && !IS_DEVICE(file->mode)) {
|
||||
if (do_ftruncate(fd, offset) < 0)
|
||||
if (vfs_ftruncate(fd, offset) < 0)
|
||||
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s", full_fname(fname));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -65,123 +65,6 @@
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
int do_ftruncate(int fd, OFF_T size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
{
|
||||
#ifdef HAVE_LSEEK64
|
||||
return lseek64(fd, offset, whence);
|
||||
#else
|
||||
return lseek(fd, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPPORT_PREALLOCATION
|
||||
#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)
|
||||
{
|
||||
/* FALLOC_FL_KEEP_SIZE lets --preallocate/--inplace keep the file size at 0
|
||||
* until data is written, but a later hole-punch (for --sparse) can only
|
||||
* deallocate blocks that lie within the file's size -- with KEEP_SIZE the
|
||||
* reserved blocks sit beyond EOF and the punch silently does nothing,
|
||||
* leaving the file fully allocated. So when holes will also be punched,
|
||||
* preallocate at full size instead (write_sparse then punches the nulls). */
|
||||
int opts = (inplace || preallocate_files) && sparse_files <= 0 ? DO_FALLOC_OPTIONS : 0;
|
||||
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
|
||||
ret = fallocate(fd, opts, offset, length);
|
||||
#elif defined HAVE_SYS_FALLOCATE
|
||||
ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
|
||||
#elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
|
||||
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 (vfs_fstat(fd, &st) < 0)
|
||||
return length;
|
||||
return st.st_blocks * S_BLKSIZE;
|
||||
}
|
||||
/* With FALLOC_FL_KEEP_SIZE the blocks for [0, length) are reserved even
|
||||
* though the file size stays put. Return that reserved length (not 0) so
|
||||
* the caller's preallocated_len is meaningful: write_sparse() needs it to
|
||||
* choose do_punch_hole() over a plain lseek() when turning a null run into
|
||||
* a hole, and the receiver uses it to trim any over-preallocation. (A
|
||||
* stray 0 here, from 2019's switch to KEEP_SIZE, is why --preallocate
|
||||
* --sparse stopped producing sparse files.) */
|
||||
return length;
|
||||
}
|
||||
#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, OFF_T pos, OFF_T 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
|
||||
#else
|
||||
(void)pos;
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
/* The logical current directory (maintained by change_dir() in util1.c).
|
||||
|
||||
@@ -428,9 +428,9 @@ int copy_file(const char *source, const char *dest, int tmpfilefd, mode_t mode)
|
||||
if (vfs_fstat(ifd, &srcst) < 0)
|
||||
rsyserr(FWARNING, errno, "fstat %s", full_fname(source));
|
||||
else if (srcst.st_size > 0) {
|
||||
prealloc_len = do_fallocate(ofd, 0, srcst.st_size);
|
||||
prealloc_len = vfs_fallocate(ofd, 0, srcst.st_size);
|
||||
if (prealloc_len < 0)
|
||||
rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(dest));
|
||||
rsyserr(FWARNING, errno, "vfs_fallocate %s", full_fname(dest));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -462,7 +462,7 @@ int copy_file(const char *source, const char *dest, int tmpfilefd, mode_t mode)
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
/* If we fail to truncate, the dest file may be wrong, so we
|
||||
* must trigger the "partial transfer" error. */
|
||||
if (do_ftruncate(ofd, offset) < 0)
|
||||
if (vfs_ftruncate(ofd, offset) < 0)
|
||||
rsyserr(FERROR_XFER, errno, "ftruncate %s", full_fname(dest));
|
||||
#else
|
||||
rprintf(FERROR_XFER, "no ftruncate for over-long pre-alloc: %s", full_fname(dest));
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* vfs/fileio.c - fd-based file-data ops: ftruncate, lseek, fallocate,
|
||||
* hole-punching.
|
||||
*
|
||||
* Moved verbatim out of syscall.c.
|
||||
*
|
||||
* Copyright (C) 1998-2022 Andrew Tridgell, Martin Pool, Wayne Davison
|
||||
* Copyright (C) 2026 Wayne Davison, Andrew Tridgell
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#include "vfs/vfs_internal.h"
|
||||
#if defined HAVE_SYS_FALLOCATE && !defined HAVE_FALLOCATE
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
int vfs_ftruncate(int fd, OFF_T size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OFF_T vfs_lseek(int fd, OFF_T offset, int whence)
|
||||
{
|
||||
#ifdef HAVE_LSEEK64
|
||||
return lseek64(fd, offset, whence);
|
||||
#else
|
||||
return lseek(fd, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPPORT_PREALLOCATION
|
||||
#ifdef FALLOC_FL_KEEP_SIZE
|
||||
#define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
|
||||
#else
|
||||
#define DO_FALLOC_OPTIONS 0
|
||||
#endif
|
||||
|
||||
OFF_T vfs_fallocate(int fd, OFF_T offset, OFF_T length)
|
||||
{
|
||||
/* FALLOC_FL_KEEP_SIZE lets --preallocate/--inplace keep the file size at 0
|
||||
* until data is written, but a later hole-punch (for --sparse) can only
|
||||
* deallocate blocks that lie within the file's size -- with KEEP_SIZE the
|
||||
* reserved blocks sit beyond EOF and the punch silently does nothing,
|
||||
* leaving the file fully allocated. So when holes will also be punched,
|
||||
* preallocate at full size instead (write_sparse then punches the nulls). */
|
||||
int opts = (inplace || preallocate_files) && sparse_files <= 0 ? DO_FALLOC_OPTIONS : 0;
|
||||
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
|
||||
ret = fallocate(fd, opts, offset, length);
|
||||
#elif defined HAVE_SYS_FALLOCATE
|
||||
ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
|
||||
#elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
|
||||
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 (vfs_fstat(fd, &st) < 0)
|
||||
return length;
|
||||
return st.st_blocks * S_BLKSIZE;
|
||||
}
|
||||
/* With FALLOC_FL_KEEP_SIZE the blocks for [0, length) are reserved even
|
||||
* though the file size stays put. Return that reserved length (not 0) so
|
||||
* the caller's preallocated_len is meaningful: write_sparse() needs it to
|
||||
* choose vfs_punch_hole() over a plain lseek() when turning a null run into
|
||||
* a hole, and the receiver uses it to trim any over-preallocation. (A
|
||||
* stray 0 here, from 2019's switch to KEEP_SIZE, is why --preallocate
|
||||
* --sparse stopped producing sparse files.) */
|
||||
return length;
|
||||
}
|
||||
#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 vfs_punch_hole(int fd, OFF_T pos, OFF_T 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 (vfs_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 (vfs_lseek(fd, len, SEEK_CUR) != pos + len)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
(void)pos;
|
||||
#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;
|
||||
}
|
||||
@@ -153,4 +153,10 @@ int vfs_lutimes(const char *path, STRUCT_STAT *stp);
|
||||
int vfs_utimes(const char *path, STRUCT_STAT *stp);
|
||||
int vfs_utime(const char *path, STRUCT_STAT *stp);
|
||||
|
||||
/* fd-based file-data ops (vfs/fileio.c). */
|
||||
int vfs_ftruncate(int fd, OFF_T size);
|
||||
OFF_T vfs_lseek(int fd, OFF_T offset, int whence);
|
||||
OFF_T vfs_fallocate(int fd, OFF_T offset, OFF_T length);
|
||||
int vfs_punch_hole(int fd, OFF_T pos, OFF_T len);
|
||||
|
||||
#endif /* RSYNC_VFS_H */
|
||||
Reference in new issue
Block a user