8293122: (fs) Use file cloning in macOS version of Files::copy method
Reviewed-by: alanb
This commit is contained in:
parent
95c7c556a3
commit
a75ddb836b
src/java.base
macosx
unix/classes/sun/nio/fs
@ -33,8 +33,13 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import sun.nio.ch.IOStatus;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
import static sun.nio.fs.UnixNativeDispatcher.chown;
|
||||
import static sun.nio.fs.UnixNativeDispatcher.unlink;
|
||||
|
||||
/**
|
||||
* Bsd implementation of FileSystem
|
||||
*/
|
||||
@ -71,6 +76,38 @@ class BsdFileSystem extends UnixFileSystem {
|
||||
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the file whose path name is {@code src} to that whose path
|
||||
* name is {@code dst} using the {@code clonefile} system call.
|
||||
*
|
||||
* @param src the path of the source file
|
||||
* @param dst the path of the destination file (clone)
|
||||
* @param followLinks whether to follow links
|
||||
*
|
||||
* @return 0 on success, or IOStatus.UNSUPPORTED_CASE if the call
|
||||
* does not work with the given parameters
|
||||
*/
|
||||
private int clone(UnixPath src, UnixPath dst, boolean followLinks)
|
||||
throws IOException
|
||||
{
|
||||
int flags = followLinks ? 0 : CLONE_NOFOLLOW;
|
||||
try {
|
||||
BsdNativeDispatcher.clonefile(src, dst, flags);
|
||||
} catch (UnixException x) {
|
||||
switch (x.errno()) {
|
||||
case ENOTSUP: // cloning not supported by filesystem
|
||||
case EXDEV: // src and dst on different filesystems
|
||||
case ENOTDIR: // problematic path parameter(s)
|
||||
return IOStatus.UNSUPPORTED_CASE;
|
||||
default:
|
||||
x.rethrowAsIOException(src, dst);
|
||||
return IOStatus.THROWN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int directCopy(int dst, int src, long addressToPollForCancel)
|
||||
throws UnixException
|
||||
@ -78,6 +115,45 @@ class BsdFileSystem extends UnixFileSystem {
|
||||
return directCopy0(dst, src, addressToPollForCancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void copyFile(UnixPath source,
|
||||
UnixFileAttributes attrs,
|
||||
UnixPath target,
|
||||
Flags flags,
|
||||
long addressToPollForCancel)
|
||||
throws IOException
|
||||
{
|
||||
// Attempt to clone the source unless cancellation is not possible,
|
||||
// or attributes are not to be copied
|
||||
if (addressToPollForCancel == 0 && flags.copyPosixAttributes) {
|
||||
try {
|
||||
int res = clone(source, target, flags.followLinks);
|
||||
|
||||
if (res == 0) {
|
||||
// copy owner (not done by clonefile)
|
||||
try {
|
||||
chown(target, attrs.uid(), attrs.gid());
|
||||
} catch (UnixException x) {
|
||||
if (flags.failIfUnableToCopyPosix)
|
||||
x.rethrowAsIOException(target);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// clone or chown failed so roll back
|
||||
try {
|
||||
unlink(target);
|
||||
} catch (UnixException ignore) { }
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
// fall through to superclass method
|
||||
}
|
||||
|
||||
super.copyFile(source, attrs, target, flags, addressToPollForCancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
void copyNonPosixAttributes(int ofd, int nfd) {
|
||||
UnixUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
||||
|
@ -61,6 +61,26 @@ class BsdNativeDispatcher extends UnixNativeDispatcher {
|
||||
}
|
||||
static native byte[] getmntonname0(long pathAddress) throws UnixException;
|
||||
|
||||
/**
|
||||
* int clonefile(const char * src, const char * dst, int flags);
|
||||
*/
|
||||
static int clonefile(UnixPath src, UnixPath dst, int flags)
|
||||
throws UnixException
|
||||
{
|
||||
try (NativeBuffer srcBuffer = copyToNativeBuffer(src);
|
||||
NativeBuffer dstBuffer = copyToNativeBuffer(dst)) {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return clonefile0(srcBuffer.address(), dstBuffer.address(),
|
||||
flags);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static native int clonefile0(long srcAddress, long dstAddress,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* setattrlist(const char* path, struct attrlist* attrList, void* attrBuf,
|
||||
* size_t attrBufSize, unsigned long options)
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/clonefile.h>
|
||||
|
||||
static jfieldID entry_name;
|
||||
static jfieldID entry_dir;
|
||||
@ -225,6 +227,22 @@ Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
|
||||
return mntonname;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_fs_BsdNativeDispatcher_clonefile0(JNIEnv* env, jclass this,
|
||||
jlong srcAddress, jlong dstAddress, jint flags)
|
||||
{
|
||||
const char* src = (const char*)jlong_to_ptr(srcAddress);
|
||||
const char* dst = (const char*)jlong_to_ptr(dstAddress);
|
||||
|
||||
int ret = clonefile(src, dst, flags);
|
||||
if (ret != 0) {
|
||||
throwUnixException(env, errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
||||
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sys/stat.h>
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
#include <sys/attr.h>
|
||||
#include <sys/clonefile.h>
|
||||
#endif
|
||||
|
||||
/* To be able to name the Java constants the same as the C constants without
|
||||
@ -133,6 +134,10 @@ class UnixConstants {
|
||||
static final int PREFIX_ERANGE = ERANGE;
|
||||
static final int PREFIX_EMFILE = EMFILE;
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
static final int PREFIX_ENOTSUP = ENOTSUP;
|
||||
#endif
|
||||
|
||||
// flags used with openat/unlinkat/etc.
|
||||
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
|
||||
static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW;
|
||||
@ -144,6 +149,10 @@ class UnixConstants {
|
||||
#endif
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
// flags used with clonefile
|
||||
static final int PREFIX_CLONE_NOFOLLOW = CLONE_NOFOLLOW;
|
||||
static final int PREFIX_CLONE_NOOWNERCOPY = CLONE_NOOWNERCOPY;
|
||||
|
||||
// flags used with setattrlist
|
||||
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
|
||||
static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME;
|
||||
|
@ -428,7 +428,7 @@ abstract class UnixFileSystem
|
||||
}
|
||||
|
||||
// The flags that control how a file is copied or moved
|
||||
private static class Flags {
|
||||
protected static class Flags {
|
||||
boolean replaceExisting;
|
||||
boolean atomicMove;
|
||||
boolean followLinks;
|
||||
|
Loading…
x
Reference in New Issue
Block a user