32
32
33
33
#if defined(__linux__ )
34
34
#include <sys/sendfile.h>
35
+ #elif defined(_ALLBSD_SOURCE )
36
+ #include <copyfile.h>
35
37
#endif
36
-
37
38
#include "sun_nio_fs_UnixCopyFile.h"
38
39
39
40
#define RESTARTABLE (_cmd , _result ) do { \
@@ -50,6 +51,23 @@ static void throwUnixException(JNIEnv* env, int errnum) {
50
51
}
51
52
}
52
53
54
+ #if defined(_ALLBSD_SOURCE )
55
+ int fcopyfile_callback (int what , int stage , copyfile_state_t state ,
56
+ const char * src , const char * dst , void * cancel )
57
+ {
58
+ if (what == COPYFILE_COPY_DATA ) {
59
+ if (stage == COPYFILE_ERR
60
+ || (stage == COPYFILE_PROGRESS && * ((int * )cancel ) != 0 )) {
61
+ // errno will be set to ECANCELED if the operation is cancelled,
62
+ // or to the appropriate error number if there is an error,
63
+ // but in either case we need to quit.
64
+ return COPYFILE_QUIT ;
65
+ }
66
+ }
67
+ return COPYFILE_CONTINUE ;
68
+ }
69
+ #endif
70
+
53
71
/**
54
72
* Transfer all bytes from src to dst within the kernel if possible (Linux),
55
73
* otherwise via user-space buffers
@@ -62,10 +80,11 @@ Java_sun_nio_fs_UnixCopyFile_transfer
62
80
63
81
#if defined(__linux__ )
64
82
// Transfer within the kernel
65
- const size_t count = 1048576 ; // 1 MB to give cancellation a chance
83
+ const size_t count = cancel != NULL ?
84
+ 1048576 : // 1 MB to give cancellation a chance
85
+ 0x7ffff000 ; // maximum number of bytes that sendfile() can transfer
66
86
ssize_t bytes_sent ;
67
87
do {
68
- // sendfile() can transfer at most 0x7ffff000 bytes
69
88
RESTARTABLE (sendfile64 (dst , src , NULL , count ), bytes_sent );
70
89
if (bytes_sent == -1 ) {
71
90
throwUnixException (env , errno );
@@ -76,6 +95,24 @@ Java_sun_nio_fs_UnixCopyFile_transfer
76
95
return ;
77
96
}
78
97
} while (bytes_sent > 0 );
98
+ #elif defined(_ALLBSD_SOURCE )
99
+ copyfile_state_t state ;
100
+ if (cancel != NULL ) {
101
+ state = copyfile_state_alloc ();
102
+ copyfile_state_set (state , COPYFILE_STATE_STATUS_CB , fcopyfile_callback );
103
+ copyfile_state_set (state , COPYFILE_STATE_STATUS_CTX , (void * )cancel );
104
+ } else {
105
+ state = NULL ;
106
+ }
107
+ if (fcopyfile (src , dst , state , COPYFILE_DATA ) < 0 ) {
108
+ int errno_fcopyfile = errno ;
109
+ if (state != NULL )
110
+ copyfile_state_free (state );
111
+ throwUnixException (env , errno_fcopyfile );
112
+ return ;
113
+ }
114
+ if (state != NULL )
115
+ copyfile_state_free (state );
79
116
#else
80
117
// Transfer via user-space buffers
81
118
char buf [8192 ];
0 commit comments