/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* 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;
flags.followLinks = true;
flags.replaceExisting = true;
continue;
}
flags.followLinks = false;
continue;
}
// 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;
}
flags.interruptible = true;
continue;
}
throw new NullPointerException();
throw new UnsupportedOperationException("Unsupported copy option");
}
return flags;
}
flags.atomicMove = true;
continue;
}
flags.replaceExisting = true;
continue;
}
// ignore
continue;
}
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
throws IOException
{
try {
} catch (UnixException x) {
}
// no attributes to copy
if (!flags.copyBasicAttributes &&
!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 {
} catch (UnixException x) {
// access to target directory required to copy named attributes
}
}
boolean done = false;
try {
// copy owner/group/permissions
if (flags.copyPosixAttributes){
try {
if (dfd >= 0) {
} else {
}
} catch (UnixException x) {
}
}
// copy other attributes
int sfd = -1;
try {
} catch (UnixException x) {
}
if (sfd >= 0) {
}
}
// copy time stamps last
if (flags.copyBasicAttributes) {
try {
if (dfd >= 0) {
} else {
}
} catch (UnixException x) {
// unable to set times
}
}
done = true;
} finally {
if (dfd >= 0)
if (!done) {
// rollback
}
}
}
// copy regular file from source to target
long addressToPollForCancel)
throws IOException
{
int fi = -1;
try {
} catch (UnixException x) {
}
try {
// open new file
int fo = -1;
try {
(O_WRONLY |
O_CREAT |
O_EXCL),
} catch (UnixException x) {
}
// set to true when file and attributes copied
boolean complete = false;
try {
// transfer bytes to target file
try {
} catch (UnixException x) {
}
// copy owner/permissions
if (flags.copyPosixAttributes) {
try {
} catch (UnixException x) {
}
}
// copy non POSIX attributes (depends on file system)
if (flags.copyNonPosixAttributes) {
}
// copy time attributes
if (flags.copyBasicAttributes) {
try {
} catch (UnixException x) {
}
}
complete = true;
} finally {
// copy of file or attributes failed so rollback
if (!complete) {
try {
} catch (UnixException ignore) { }
}
}
} finally {
}
}
// copy symbolic link from source to target
throws IOException
{
byte[] linktarget = null;
try {
} catch (UnixException x) {
}
try {
if (flags.copyPosixAttributes) {
try {
} catch (UnixException x) {
// ignore since link attributes not required to be copied
}
}
} catch (UnixException x) {
}
}
// copy special file from source to target
throws IOException
{
try {
} catch (UnixException x) {
}
boolean done = false;
try {
if (flags.copyPosixAttributes) {
try {
} catch (UnixException x) {
}
}
if (flags.copyBasicAttributes) {
try {
} catch (UnixException x) {
}
}
done = true;
} finally {
if (!done) {
}
}
}
// move file from source to target
throws IOException
{
// permission check
source.checkWrite();
target.checkWrite();
}
// translate options into flags
// handle atomic rename case
if (flags.atomicMove) {
try {
} catch (UnixException x) {
throw new AtomicMoveNotSupportedException(
x.errorString());
}
}
return;
}
// move using rename or copy+delete
// get attributes of source file (don't follow links)
try {
} catch (UnixException x) {
}
// get attributes of target file (don't follow links)
try {
} catch (UnixException x) {
// ignore
}
// 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) {
return; // nothing to do as files are identical
if (!flags.replaceExisting) {
throw new FileAlreadyExistsException(
}
// attempt to delete target
try {
if (targetAttrs.isDirectory()) {
} else {
}
} catch (UnixException x) {
// target is non-empty directory that can't be replaced.
if (targetAttrs.isDirectory() &&
{
throw new DirectoryNotEmptyException(
}
}
}
// first try rename
try {
return;
} catch (UnixException x) {
}
}
// copy source to target
if (sourceAttrs.isDirectory()) {
} else {
if (sourceAttrs.isSymbolicLink()) {
} else {
if (sourceAttrs.isDevice()) {
} else {
}
}
}
// delete source
try {
if (sourceAttrs.isDirectory()) {
} else {
}
} 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()) {
} else {
}
} catch (UnixException ignore) { }
if (sourceAttrs.isDirectory() &&
{
throw new DirectoryNotEmptyException(
}
}
}
// copy file from source to target
{
// permission checks
target.checkWrite();
}
// translate options into flags
// get attributes of source file
try {
} catch (UnixException x) {
}
// if source file is symbolic link then we must check LinkPermission
}
// get attributes of target file (don't follow links)
try {
} catch (UnixException x) {
// ignore
}
// 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) {
return; // nothing to do as files are identical
if (!flags.replaceExisting)
throw new FileAlreadyExistsException(
try {
if (targetAttrs.isDirectory()) {
} else {
}
} catch (UnixException x) {
// target is non-empty directory that can't be replaced.
if (targetAttrs.isDirectory() &&
{
throw new DirectoryNotEmptyException(
}
}
}
// do the copy
if (sourceAttrs.isDirectory()) {
return;
}
if (sourceAttrs.isSymbolicLink()) {
return;
}
if (!flags.interruptible) {
// non-interruptible file copy
return;
}
// interruptible file copy
}
};
try {
} catch (ExecutionException e) {
if (t instanceof IOException)
throw (IOException)t;
throw new IOException(t);
}
}
// -- native methods --
throws UnixException;
static {
return null;
}});
}
}