mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8293122: (fs) Use file cloning in macOS version of Files::copy method
Reviewed-by: alanb
This commit is contained in:
parent
95c7c556a3
commit
a75ddb836b
5 changed files with 124 additions and 1 deletions
|
@ -33,8 +33,13 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import sun.nio.ch.IOStatus;
|
||||||
import sun.security.action.GetPropertyAction;
|
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
|
* Bsd implementation of FileSystem
|
||||||
*/
|
*/
|
||||||
|
@ -71,6 +76,38 @@ class BsdFileSystem extends UnixFileSystem {
|
||||||
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
|
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
|
@Override
|
||||||
protected int directCopy(int dst, int src, long addressToPollForCancel)
|
protected int directCopy(int dst, int src, long addressToPollForCancel)
|
||||||
throws UnixException
|
throws UnixException
|
||||||
|
@ -78,6 +115,45 @@ class BsdFileSystem extends UnixFileSystem {
|
||||||
return directCopy0(dst, src, addressToPollForCancel);
|
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
|
@Override
|
||||||
void copyNonPosixAttributes(int ofd, int nfd) {
|
void copyNonPosixAttributes(int ofd, int nfd) {
|
||||||
UnixUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
UnixUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
||||||
|
|
|
@ -61,6 +61,26 @@ class BsdNativeDispatcher extends UnixNativeDispatcher {
|
||||||
}
|
}
|
||||||
static native byte[] getmntonname0(long pathAddress) throws UnixException;
|
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,
|
* setattrlist(const char* path, struct attrlist* attrList, void* attrBuf,
|
||||||
* size_t attrBufSize, unsigned long options)
|
* size_t attrBufSize, unsigned long options)
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/attr.h>
|
||||||
|
#include <sys/clonefile.h>
|
||||||
|
|
||||||
static jfieldID entry_name;
|
static jfieldID entry_name;
|
||||||
static jfieldID entry_dir;
|
static jfieldID entry_dir;
|
||||||
|
@ -225,6 +227,22 @@ Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
|
||||||
return mntonname;
|
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
|
JNIEXPORT void JNICALL
|
||||||
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
||||||
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
|
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef _ALLBSD_SOURCE
|
#ifdef _ALLBSD_SOURCE
|
||||||
#include <sys/attr.h>
|
#include <sys/attr.h>
|
||||||
|
#include <sys/clonefile.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* To be able to name the Java constants the same as the C constants without
|
/* 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_ERANGE = ERANGE;
|
||||||
static final int PREFIX_EMFILE = EMFILE;
|
static final int PREFIX_EMFILE = EMFILE;
|
||||||
|
|
||||||
|
#ifdef _ALLBSD_SOURCE
|
||||||
|
static final int PREFIX_ENOTSUP = ENOTSUP;
|
||||||
|
#endif
|
||||||
|
|
||||||
// flags used with openat/unlinkat/etc.
|
// flags used with openat/unlinkat/etc.
|
||||||
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
|
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR)
|
||||||
static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW;
|
static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW;
|
||||||
|
@ -144,6 +149,10 @@ class UnixConstants {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _ALLBSD_SOURCE
|
#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
|
// flags used with setattrlist
|
||||||
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
|
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
|
||||||
static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME;
|
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
|
// The flags that control how a file is copied or moved
|
||||||
private static class Flags {
|
protected static class Flags {
|
||||||
boolean replaceExisting;
|
boolean replaceExisting;
|
||||||
boolean atomicMove;
|
boolean atomicMove;
|
||||||
boolean followLinks;
|
boolean followLinks;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue