Skip to content

Commit a75ddb8

Browse files
author
Brian Burkhalter
committedSep 14, 2022
8293122: (fs) Use file cloning in macOS version of Files::copy method
Reviewed-by: alanb
1 parent 95c7c55 commit a75ddb8

File tree

5 files changed

+124
-1
lines changed

5 files changed

+124
-1
lines changed
 

‎src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java

+76
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@
3333
import java.util.Collections;
3434
import java.util.HashSet;
3535
import java.util.Set;
36+
import sun.nio.ch.IOStatus;
3637
import sun.security.action.GetPropertyAction;
3738

39+
import static sun.nio.fs.UnixConstants.*;
40+
import static sun.nio.fs.UnixNativeDispatcher.chown;
41+
import static sun.nio.fs.UnixNativeDispatcher.unlink;
42+
3843
/**
3944
* Bsd implementation of FileSystem
4045
*/
@@ -71,13 +76,84 @@ public Set<String> supportedFileAttributeViews() {
7176
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
7277
}
7378

79+
/**
80+
* Clones the file whose path name is {@code src} to that whose path
81+
* name is {@code dst} using the {@code clonefile} system call.
82+
*
83+
* @param src the path of the source file
84+
* @param dst the path of the destination file (clone)
85+
* @param followLinks whether to follow links
86+
*
87+
* @return 0 on success, or IOStatus.UNSUPPORTED_CASE if the call
88+
* does not work with the given parameters
89+
*/
90+
private int clone(UnixPath src, UnixPath dst, boolean followLinks)
91+
throws IOException
92+
{
93+
int flags = followLinks ? 0 : CLONE_NOFOLLOW;
94+
try {
95+
BsdNativeDispatcher.clonefile(src, dst, flags);
96+
} catch (UnixException x) {
97+
switch (x.errno()) {
98+
case ENOTSUP: // cloning not supported by filesystem
99+
case EXDEV: // src and dst on different filesystems
100+
case ENOTDIR: // problematic path parameter(s)
101+
return IOStatus.UNSUPPORTED_CASE;
102+
default:
103+
x.rethrowAsIOException(src, dst);
104+
return IOStatus.THROWN;
105+
}
106+
}
107+
108+
return 0;
109+
}
110+
74111
@Override
75112
protected int directCopy(int dst, int src, long addressToPollForCancel)
76113
throws UnixException
77114
{
78115
return directCopy0(dst, src, addressToPollForCancel);
79116
}
80117

118+
@Override
119+
protected void copyFile(UnixPath source,
120+
UnixFileAttributes attrs,
121+
UnixPath target,
122+
Flags flags,
123+
long addressToPollForCancel)
124+
throws IOException
125+
{
126+
// Attempt to clone the source unless cancellation is not possible,
127+
// or attributes are not to be copied
128+
if (addressToPollForCancel == 0 && flags.copyPosixAttributes) {
129+
try {
130+
int res = clone(source, target, flags.followLinks);
131+
132+
if (res == 0) {
133+
// copy owner (not done by clonefile)
134+
try {
135+
chown(target, attrs.uid(), attrs.gid());
136+
} catch (UnixException x) {
137+
if (flags.failIfUnableToCopyPosix)
138+
x.rethrowAsIOException(target);
139+
}
140+
return;
141+
}
142+
} catch (IOException e) {
143+
// clone or chown failed so roll back
144+
try {
145+
unlink(target);
146+
} catch (UnixException ignore) { }
147+
148+
throw e;
149+
}
150+
151+
// fall through to superclass method
152+
}
153+
154+
super.copyFile(source, attrs, target, flags, addressToPollForCancel);
155+
}
156+
81157
@Override
82158
void copyNonPosixAttributes(int ofd, int nfd) {
83159
UnixUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);

‎src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java

+20
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,26 @@ static byte[] getmntonname(UnixPath path) throws UnixException {
6161
}
6262
static native byte[] getmntonname0(long pathAddress) throws UnixException;
6363

64+
/**
65+
* int clonefile(const char * src, const char * dst, int flags);
66+
*/
67+
static int clonefile(UnixPath src, UnixPath dst, int flags)
68+
throws UnixException
69+
{
70+
try (NativeBuffer srcBuffer = copyToNativeBuffer(src);
71+
NativeBuffer dstBuffer = copyToNativeBuffer(dst)) {
72+
long comp = Blocker.begin();
73+
try {
74+
return clonefile0(srcBuffer.address(), dstBuffer.address(),
75+
flags);
76+
} finally {
77+
Blocker.end(comp);
78+
}
79+
}
80+
}
81+
private static native int clonefile0(long srcAddress, long dstAddress,
82+
int flags);
83+
6484
/**
6585
* setattrlist(const char* path, struct attrlist* attrList, void* attrBuf,
6686
* size_t attrBufSize, unsigned long options)

‎src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c

+18
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
#include <stdlib.h>
4444
#include <string.h>
45+
#include <sys/attr.h>
46+
#include <sys/clonefile.h>
4547

4648
static jfieldID entry_name;
4749
static jfieldID entry_dir;
@@ -225,6 +227,22 @@ Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
225227
return mntonname;
226228
}
227229

230+
JNIEXPORT jint JNICALL
231+
Java_sun_nio_fs_BsdNativeDispatcher_clonefile0(JNIEnv* env, jclass this,
232+
jlong srcAddress, jlong dstAddress, jint flags)
233+
{
234+
const char* src = (const char*)jlong_to_ptr(srcAddress);
235+
const char* dst = (const char*)jlong_to_ptr(dstAddress);
236+
237+
int ret = clonefile(src, dst, flags);
238+
if (ret != 0) {
239+
throwUnixException(env, errno);
240+
return ret;
241+
}
242+
243+
return 0;
244+
}
245+
228246
JNIEXPORT void JNICALL
229247
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
230248
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,

‎src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <sys/stat.h>
3333
#ifdef _ALLBSD_SOURCE
3434
#include <sys/attr.h>
35+
#include <sys/clonefile.h>
3536
#endif
3637

3738
/* To be able to name the Java constants the same as the C constants without
@@ -133,6 +134,10 @@ class UnixConstants {
133134
static final int PREFIX_ERANGE = ERANGE;
134135
static final int PREFIX_EMFILE = EMFILE;
135136

137+
#ifdef _ALLBSD_SOURCE
138+
static final int PREFIX_ENOTSUP = ENOTSUP;
139+
#endif
140+
136141
// flags used with openat/unlinkat/etc.
137142
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
138143
static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW;
@@ -144,6 +149,10 @@ class UnixConstants {
144149
#endif
145150

146151
#ifdef _ALLBSD_SOURCE
152+
// flags used with clonefile
153+
static final int PREFIX_CLONE_NOFOLLOW = CLONE_NOFOLLOW;
154+
static final int PREFIX_CLONE_NOOWNERCOPY = CLONE_NOOWNERCOPY;
155+
147156
// flags used with setattrlist
148157
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
149158
static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME;

‎src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ private static int temporaryBufferSize(UnixPath source, UnixPath target) {
428428
}
429429

430430
// The flags that control how a file is copied or moved
431-
private static class Flags {
431+
protected static class Flags {
432432
boolean replaceExisting;
433433
boolean atomicMove;
434434
boolean followLinks;

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Sep 14, 2022

@openjdk-notifier[bot]
Please sign in to comment.