621 lines
22 KiB
Java
621 lines
22 KiB
Java
![]() |
/*
|
||
|
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||
|
*
|
||
|
* This code is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License version 2 only, as
|
||
|
* published by the Free Software Foundation. Oracle designates this
|
||
|
* particular file as subject to the "Classpath" exception as provided
|
||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||
|
*
|
||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||
|
* accompanied this code).
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License version
|
||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
*
|
||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||
|
* or visit www.oracle.com if you need additional information or have any
|
||
|
* questions.
|
||
|
*/
|
||
|
|
||
|
package sun.nio.fs;
|
||
|
|
||
|
import java.nio.file.*;
|
||
|
import java.io.IOException;
|
||
|
import java.security.AccessController;
|
||
|
import java.security.PrivilegedAction;
|
||
|
import java.util.concurrent.ExecutionException;
|
||
|
import java.util.concurrent.TimeUnit;
|
||
|
import com.sun.nio.file.ExtendedCopyOption;
|
||
|
|
||
|
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||
|
import static sun.nio.fs.UnixConstants.*;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Unix implementation of Path#copyTo and Path#moveTo methods.
|
||
|
*/
|
||
|
|
||
|
class UnixCopyFile {
|
||
|
private UnixCopyFile() { }
|
||
|
|
||
|
// The flags that control how a file is copied or moved
|
||
|
private static class Flags {
|
||
|
boolean replaceExisting;
|
||
|
boolean atomicMove;
|
||
|
boolean followLinks;
|
||
|
boolean interruptible;
|
||
|
|
||
|
// the attributes to copy
|
||
|
boolean copyBasicAttributes;
|
||
|
boolean copyPosixAttributes;
|
||
|
boolean copyNonPosixAttributes;
|
||
|
|
||
|
// flags that indicate if we should fail if attributes cannot be copied
|
||
|
boolean failIfUnableToCopyBasic;
|
||
|
boolean failIfUnableToCopyPosix;
|
||
|
boolean failIfUnableToCopyNonPosix;
|
||
|
|
||
|
static Flags fromCopyOptions(CopyOption... options) {
|
||
|
Flags flags = new Flags();
|
||
|
flags.followLinks = true;
|
||
|
for (CopyOption option: options) {
|
||
|
if (option == StandardCopyOption.REPLACE_EXISTING) {
|
||
|
flags.replaceExisting = true;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||
|
flags.followLinks = false;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == StandardCopyOption.COPY_ATTRIBUTES) {
|
||
|
// copy all attributes but only fail if basic attributes
|
||
|
// cannot be copied
|
||
|
flags.copyBasicAttributes = true;
|
||
|
flags.copyPosixAttributes = true;
|
||
|
flags.copyNonPosixAttributes = true;
|
||
|
flags.failIfUnableToCopyBasic = true;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == ExtendedCopyOption.INTERRUPTIBLE) {
|
||
|
flags.interruptible = true;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == null)
|
||
|
throw new NullPointerException();
|
||
|
throw new UnsupportedOperationException("Unsupported copy option");
|
||
|
}
|
||
|
return flags;
|
||
|
}
|
||
|
|
||
|
static Flags fromMoveOptions(CopyOption... options) {
|
||
|
Flags flags = new Flags();
|
||
|
for (CopyOption option: options) {
|
||
|
if (option == StandardCopyOption.ATOMIC_MOVE) {
|
||
|
flags.atomicMove = true;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == StandardCopyOption.REPLACE_EXISTING) {
|
||
|
flags.replaceExisting = true;
|
||
|
continue;
|
||
|
}
|
||
|
if (option == LinkOption.NOFOLLOW_LINKS) {
|
||
|
// ignore
|
||
|
continue;
|
||
|
}
|
||
|
if (option == null)
|
||
|
throw new NullPointerException();
|
||
|
throw new UnsupportedOperationException("Unsupported copy option");
|
||
|
}
|
||
|
|
||
|
// a move requires that all attributes be copied but only fail if
|
||
|
// the basic attributes cannot be copied
|
||
|
flags.copyBasicAttributes = true;
|
||
|
flags.copyPosixAttributes = true;
|
||
|
flags.copyNonPosixAttributes = true;
|
||
|
flags.failIfUnableToCopyBasic = true;
|
||
|
return flags;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy directory from source to target
|
||
|
private static void copyDirectory(UnixPath source,
|
||
|
UnixFileAttributes attrs,
|
||
|
UnixPath target,
|
||
|
Flags flags)
|
||
|
throws IOException
|
||
|
{
|
||
|
try {
|
||
|
mkdir(target, attrs.mode());
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
|
||
|
// no attributes to copy
|
||
|
if (!flags.copyBasicAttributes &&
|
||
|
!flags.copyPosixAttributes &&
|
||
|
!flags.copyNonPosixAttributes) return;
|
||
|
|
||
|
// open target directory if possible (this can fail when copying a
|
||
|
// directory for which we don't have read access).
|
||
|
int dfd = -1;
|
||
|
try {
|
||
|
dfd = open(target, O_RDONLY, 0);
|
||
|
} catch (UnixException x) {
|
||
|
// access to target directory required to copy named attributes
|
||
|
if (flags.copyNonPosixAttributes && flags.failIfUnableToCopyNonPosix) {
|
||
|
try { rmdir(target); } catch (UnixException ignore) { }
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean done = false;
|
||
|
try {
|
||
|
// copy owner/group/permissions
|
||
|
if (flags.copyPosixAttributes){
|
||
|
try {
|
||
|
if (dfd >= 0) {
|
||
|
fchown(dfd, attrs.uid(), attrs.gid());
|
||
|
fchmod(dfd, attrs.mode());
|
||
|
} else {
|
||
|
chown(target, attrs.uid(), attrs.gid());
|
||
|
chmod(target, attrs.mode());
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
// unable to set owner/group
|
||
|
if (flags.failIfUnableToCopyPosix)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
// copy other attributes
|
||
|
if (flags.copyNonPosixAttributes && (dfd >= 0)) {
|
||
|
int sfd = -1;
|
||
|
try {
|
||
|
sfd = open(source, O_RDONLY, 0);
|
||
|
} catch (UnixException x) {
|
||
|
if (flags.failIfUnableToCopyNonPosix)
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
if (sfd >= 0) {
|
||
|
source.getFileSystem().copyNonPosixAttributes(sfd, dfd);
|
||
|
close(sfd);
|
||
|
}
|
||
|
}
|
||
|
// copy time stamps last
|
||
|
if (flags.copyBasicAttributes) {
|
||
|
try {
|
||
|
if (dfd >= 0 && futimesSupported()) {
|
||
|
futimes(dfd,
|
||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||
|
} else {
|
||
|
utimes(target,
|
||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
// unable to set times
|
||
|
if (flags.failIfUnableToCopyBasic)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
done = true;
|
||
|
} finally {
|
||
|
if (dfd >= 0)
|
||
|
close(dfd);
|
||
|
if (!done) {
|
||
|
// rollback
|
||
|
try { rmdir(target); } catch (UnixException ignore) { }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy regular file from source to target
|
||
|
private static void copyFile(UnixPath source,
|
||
|
UnixFileAttributes attrs,
|
||
|
UnixPath target,
|
||
|
Flags flags,
|
||
|
long addressToPollForCancel)
|
||
|
throws IOException
|
||
|
{
|
||
|
int fi = -1;
|
||
|
try {
|
||
|
fi = open(source, O_RDONLY, 0);
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
// open new file
|
||
|
int fo = -1;
|
||
|
try {
|
||
|
fo = open(target,
|
||
|
(O_WRONLY |
|
||
|
O_CREAT |
|
||
|
O_EXCL),
|
||
|
attrs.mode());
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
|
||
|
// set to true when file and attributes copied
|
||
|
boolean complete = false;
|
||
|
try {
|
||
|
// transfer bytes to target file
|
||
|
try {
|
||
|
transfer(fo, fi, addressToPollForCancel);
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(source, target);
|
||
|
}
|
||
|
// copy owner/permissions
|
||
|
if (flags.copyPosixAttributes) {
|
||
|
try {
|
||
|
fchown(fo, attrs.uid(), attrs.gid());
|
||
|
fchmod(fo, attrs.mode());
|
||
|
} catch (UnixException x) {
|
||
|
if (flags.failIfUnableToCopyPosix)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
// copy non POSIX attributes (depends on file system)
|
||
|
if (flags.copyNonPosixAttributes) {
|
||
|
source.getFileSystem().copyNonPosixAttributes(fi, fo);
|
||
|
}
|
||
|
// copy time attributes
|
||
|
if (flags.copyBasicAttributes) {
|
||
|
try {
|
||
|
if (futimesSupported()) {
|
||
|
futimes(fo,
|
||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||
|
} else {
|
||
|
utimes(target,
|
||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
if (flags.failIfUnableToCopyBasic)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
complete = true;
|
||
|
} finally {
|
||
|
close(fo);
|
||
|
|
||
|
// copy of file or attributes failed so rollback
|
||
|
if (!complete) {
|
||
|
try {
|
||
|
unlink(target);
|
||
|
} catch (UnixException ignore) { }
|
||
|
}
|
||
|
}
|
||
|
} finally {
|
||
|
close(fi);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy symbolic link from source to target
|
||
|
private static void copyLink(UnixPath source,
|
||
|
UnixFileAttributes attrs,
|
||
|
UnixPath target,
|
||
|
Flags flags)
|
||
|
throws IOException
|
||
|
{
|
||
|
byte[] linktarget = null;
|
||
|
try {
|
||
|
linktarget = readlink(source);
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
try {
|
||
|
symlink(linktarget, target);
|
||
|
|
||
|
if (flags.copyPosixAttributes) {
|
||
|
try {
|
||
|
lchown(target, attrs.uid(), attrs.gid());
|
||
|
} catch (UnixException x) {
|
||
|
// ignore since link attributes not required to be copied
|
||
|
}
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy special file from source to target
|
||
|
private static void copySpecial(UnixPath source,
|
||
|
UnixFileAttributes attrs,
|
||
|
UnixPath target,
|
||
|
Flags flags)
|
||
|
throws IOException
|
||
|
{
|
||
|
try {
|
||
|
mknod(target, attrs.mode(), attrs.rdev());
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
boolean done = false;
|
||
|
try {
|
||
|
if (flags.copyPosixAttributes) {
|
||
|
try {
|
||
|
chown(target, attrs.uid(), attrs.gid());
|
||
|
chmod(target, attrs.mode());
|
||
|
} catch (UnixException x) {
|
||
|
if (flags.failIfUnableToCopyPosix)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
if (flags.copyBasicAttributes) {
|
||
|
try {
|
||
|
utimes(target,
|
||
|
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
|
||
|
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
|
||
|
} catch (UnixException x) {
|
||
|
if (flags.failIfUnableToCopyBasic)
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
done = true;
|
||
|
} finally {
|
||
|
if (!done) {
|
||
|
try { unlink(target); } catch (UnixException ignore) { }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move file from source to target
|
||
|
static void move(UnixPath source, UnixPath target, CopyOption... options)
|
||
|
throws IOException
|
||
|
{
|
||
|
// permission check
|
||
|
SecurityManager sm = System.getSecurityManager();
|
||
|
if (sm != null) {
|
||
|
source.checkWrite();
|
||
|
target.checkWrite();
|
||
|
}
|
||
|
|
||
|
// translate options into flags
|
||
|
Flags flags = Flags.fromMoveOptions(options);
|
||
|
|
||
|
// handle atomic rename case
|
||
|
if (flags.atomicMove) {
|
||
|
try {
|
||
|
rename(source, target);
|
||
|
} catch (UnixException x) {
|
||
|
if (x.errno() == EXDEV) {
|
||
|
throw new AtomicMoveNotSupportedException(
|
||
|
source.getPathForExceptionMessage(),
|
||
|
target.getPathForExceptionMessage(),
|
||
|
x.errorString());
|
||
|
}
|
||
|
x.rethrowAsIOException(source, target);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// move using rename or copy+delete
|
||
|
UnixFileAttributes sourceAttrs = null;
|
||
|
UnixFileAttributes targetAttrs = null;
|
||
|
|
||
|
// get attributes of source file (don't follow links)
|
||
|
try {
|
||
|
sourceAttrs = UnixFileAttributes.get(source, false);
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
|
||
|
// get attributes of target file (don't follow links)
|
||
|
try {
|
||
|
targetAttrs = UnixFileAttributes.get(target, false);
|
||
|
} catch (UnixException x) {
|
||
|
// ignore
|
||
|
}
|
||
|
boolean targetExists = (targetAttrs != null);
|
||
|
|
||
|
// if the target exists:
|
||
|
// 1. check if source and target are the same file
|
||
|
// 2. throw exception if REPLACE_EXISTING option is not set
|
||
|
// 3. delete target if REPLACE_EXISTING option set
|
||
|
if (targetExists) {
|
||
|
if (sourceAttrs.isSameFile(targetAttrs))
|
||
|
return; // nothing to do as files are identical
|
||
|
if (!flags.replaceExisting) {
|
||
|
throw new FileAlreadyExistsException(
|
||
|
target.getPathForExceptionMessage());
|
||
|
}
|
||
|
|
||
|
// attempt to delete target
|
||
|
try {
|
||
|
if (targetAttrs.isDirectory()) {
|
||
|
rmdir(target);
|
||
|
} else {
|
||
|
unlink(target);
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
// target is non-empty directory that can't be replaced.
|
||
|
if (targetAttrs.isDirectory() &&
|
||
|
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||
|
{
|
||
|
throw new DirectoryNotEmptyException(
|
||
|
target.getPathForExceptionMessage());
|
||
|
}
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// first try rename
|
||
|
try {
|
||
|
rename(source, target);
|
||
|
return;
|
||
|
} catch (UnixException x) {
|
||
|
if (x.errno() != EXDEV && x.errno() != EISDIR) {
|
||
|
x.rethrowAsIOException(source, target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy source to target
|
||
|
if (sourceAttrs.isDirectory()) {
|
||
|
copyDirectory(source, sourceAttrs, target, flags);
|
||
|
} else {
|
||
|
if (sourceAttrs.isSymbolicLink()) {
|
||
|
copyLink(source, sourceAttrs, target, flags);
|
||
|
} else {
|
||
|
if (sourceAttrs.isDevice()) {
|
||
|
copySpecial(source, sourceAttrs, target, flags);
|
||
|
} else {
|
||
|
copyFile(source, sourceAttrs, target, flags, 0L);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// delete source
|
||
|
try {
|
||
|
if (sourceAttrs.isDirectory()) {
|
||
|
rmdir(source);
|
||
|
} else {
|
||
|
unlink(source);
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
// file was copied but unable to unlink the source file so attempt
|
||
|
// to remove the target and throw a reasonable exception
|
||
|
try {
|
||
|
if (sourceAttrs.isDirectory()) {
|
||
|
rmdir(target);
|
||
|
} else {
|
||
|
unlink(target);
|
||
|
}
|
||
|
} catch (UnixException ignore) { }
|
||
|
|
||
|
if (sourceAttrs.isDirectory() &&
|
||
|
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||
|
{
|
||
|
throw new DirectoryNotEmptyException(
|
||
|
source.getPathForExceptionMessage());
|
||
|
}
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// copy file from source to target
|
||
|
static void copy(final UnixPath source,
|
||
|
final UnixPath target,
|
||
|
CopyOption... options) throws IOException
|
||
|
{
|
||
|
// permission checks
|
||
|
SecurityManager sm = System.getSecurityManager();
|
||
|
if (sm != null) {
|
||
|
source.checkRead();
|
||
|
target.checkWrite();
|
||
|
}
|
||
|
|
||
|
// translate options into flags
|
||
|
final Flags flags = Flags.fromCopyOptions(options);
|
||
|
|
||
|
UnixFileAttributes sourceAttrs = null;
|
||
|
UnixFileAttributes targetAttrs = null;
|
||
|
|
||
|
// get attributes of source file
|
||
|
try {
|
||
|
sourceAttrs = UnixFileAttributes.get(source, flags.followLinks);
|
||
|
} catch (UnixException x) {
|
||
|
x.rethrowAsIOException(source);
|
||
|
}
|
||
|
|
||
|
// if source file is symbolic link then we must check LinkPermission
|
||
|
if (sm != null && sourceAttrs.isSymbolicLink()) {
|
||
|
sm.checkPermission(new LinkPermission("symbolic"));
|
||
|
}
|
||
|
|
||
|
// get attributes of target file (don't follow links)
|
||
|
try {
|
||
|
targetAttrs = UnixFileAttributes.get(target, false);
|
||
|
} catch (UnixException x) {
|
||
|
// ignore
|
||
|
}
|
||
|
boolean targetExists = (targetAttrs != null);
|
||
|
|
||
|
// if the target exists:
|
||
|
// 1. check if source and target are the same file
|
||
|
// 2. throw exception if REPLACE_EXISTING option is not set
|
||
|
// 3. try to unlink the target
|
||
|
if (targetExists) {
|
||
|
if (sourceAttrs.isSameFile(targetAttrs))
|
||
|
return; // nothing to do as files are identical
|
||
|
if (!flags.replaceExisting)
|
||
|
throw new FileAlreadyExistsException(
|
||
|
target.getPathForExceptionMessage());
|
||
|
try {
|
||
|
if (targetAttrs.isDirectory()) {
|
||
|
rmdir(target);
|
||
|
} else {
|
||
|
unlink(target);
|
||
|
}
|
||
|
} catch (UnixException x) {
|
||
|
// target is non-empty directory that can't be replaced.
|
||
|
if (targetAttrs.isDirectory() &&
|
||
|
(x.errno() == EEXIST || x.errno() == ENOTEMPTY))
|
||
|
{
|
||
|
throw new DirectoryNotEmptyException(
|
||
|
target.getPathForExceptionMessage());
|
||
|
}
|
||
|
x.rethrowAsIOException(target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// do the copy
|
||
|
if (sourceAttrs.isDirectory()) {
|
||
|
copyDirectory(source, sourceAttrs, target, flags);
|
||
|
return;
|
||
|
}
|
||
|
if (sourceAttrs.isSymbolicLink()) {
|
||
|
copyLink(source, sourceAttrs, target, flags);
|
||
|
return;
|
||
|
}
|
||
|
if (!flags.interruptible) {
|
||
|
// non-interruptible file copy
|
||
|
copyFile(source, sourceAttrs, target, flags, 0L);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// interruptible file copy
|
||
|
final UnixFileAttributes attrsToCopy = sourceAttrs;
|
||
|
Cancellable copyTask = new Cancellable() {
|
||
|
@Override public void implRun() throws IOException {
|
||
|
copyFile(source, attrsToCopy, target, flags,
|
||
|
addressToPollForCancel());
|
||
|
}
|
||
|
};
|
||
|
try {
|
||
|
Cancellable.runInterruptibly(copyTask);
|
||
|
} catch (ExecutionException e) {
|
||
|
Throwable t = e.getCause();
|
||
|
if (t instanceof IOException)
|
||
|
throw (IOException)t;
|
||
|
throw new IOException(t);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// -- native methods --
|
||
|
|
||
|
static native void transfer(int dst, int src, long addressToPollForCancel)
|
||
|
throws UnixException;
|
||
|
|
||
|
// Android-removed: Code to load native libraries, doesn't make sense on Android.
|
||
|
/*
|
||
|
static {
|
||
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||
|
@Override
|
||
|
public Void run() {
|
||
|
System.loadLibrary("nio");
|
||
|
return null;
|
||
|
}});
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
}
|