Skip to content

Commit 809bd07

Browse files
committed
Add copy_file_range(2) support for FreeBSD and Linux
When compiling on Linux USE_COPY_FILE_RANGE must be defined
1 parent 68cb3cb commit 809bd07

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/cpdup.c

+45
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
#include "cpdup.h"
5757
#include "hclink.h"
5858
#include "hcproto.h"
59+
#if defined(__FreeBSD__)
60+
#include <sys/param.h>
61+
#endif
5962

6063
#define HSIZE 8192
6164
#define HMASK (HSIZE-1)
@@ -177,6 +180,14 @@ int64_t CountLinkedItems;
177180
static struct HostConf SrcHost;
178181
static struct HostConf DstHost;
179182

183+
#if defined(USE_COPY_FILE_RANGE) || (defined(__FreeBSD__) && __FreeBSD_version > 1300037)
184+
static inline int
185+
chk_ENOTSUP(int err)
186+
{
187+
return err == EOPNOTSUPP || (ENOTSUP != EOPNOTSUPP && err == ENOTSUP);
188+
}
189+
#endif
190+
180191
int
181192
main(int ac, char **av)
182193
{
@@ -1131,7 +1142,38 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
11311142
const char *op;
11321143
char *iobuf1 = malloc(GETIOSIZE);
11331144
int n;
1145+
#if defined(USE_COPY_FILE_RANGE) || (defined(__FreeBSD__) && __FreeBSD_version > 1300037)
1146+
int do_std_copy = 0;
11341147

1148+
/*
1149+
* For local file transfers try copy_file_range(2)
1150+
*/
1151+
if (SrcHost.host == NULL && DstHost.host == NULL) {
1152+
ssize_t wcnt;
1153+
do {
1154+
wcnt = copy_file_range(fd1, NULL, fd2, NULL,
1155+
SSIZE_MAX, 0);
1156+
} while (wcnt > 0);
1157+
if (wcnt < 0) {
1158+
/*
1159+
* On selected errnos we retry with standard copy
1160+
*/
1161+
if (errno == EINVAL || errno == EBADF ||
1162+
errno == ENOSYS || errno == EXDEV ||
1163+
errno == ETXTBSY || chk_ENOTSUP(errno))
1164+
do_std_copy = 1;
1165+
else
1166+
n = -1;
1167+
} else
1168+
n = 0;
1169+
} else
1170+
do_std_copy = 1;
1171+
1172+
/*
1173+
* Do standard copy if remote or copy_file_range(2) has failed
1174+
*/
1175+
if (do_std_copy) {
1176+
#endif
11351177
/*
11361178
* Matt: What about holes?
11371179
*/
@@ -1142,6 +1184,9 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
11421184
break;
11431185
op = "read";
11441186
}
1187+
#if defined(USE_COPY_FILE_RANGE) || (defined(__FreeBSD__) && __FreeBSD_version > 1300037)
1188+
}
1189+
#endif
11451190
hc_close(&DstHost, fd2);
11461191
if (n == 0) {
11471192
struct timeval tv[2];

0 commit comments

Comments
 (0)