8201407: Files.move throws DirectoryNonEmptyException when moving directory across file system
Reviewed-by: alanb
--- a/src/java.base/share/classes/java/nio/file/Files.java Thu Jun 07 15:10:06 2018 +0200
+++ b/src/java.base/share/classes/java/nio/file/Files.java Thu Jun 07 07:43:29 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -1391,8 +1391,9 @@
* specific exception)</i>
* @throws DirectoryNotEmptyException
* the {@code REPLACE_EXISTING} option is specified but the file
- * cannot be replaced because it is a non-empty directory
- * <i>(optional specific exception)</i>
+ * cannot be replaced because it is a non-empty directory, or the
+ * source is a non-empty directory containing entries that would
+ * be required to be moved <i>(optional specific exceptions)</i>
* @throws AtomicMoveNotSupportedException
* if the options array contains the {@code ATOMIC_MOVE} option but
* the file cannot be moved as an atomic file system operation.
--- a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java Thu Jun 07 15:10:06 2018 +0200
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java Thu Jun 07 07:43:29 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -373,6 +373,22 @@
}
}
+ // throw a DirectoryNotEmpty exception if appropriate
+ static void ensureEmptyDir(UnixPath dir) throws IOException {
+ try {
+ long ptr = opendir(dir);
+ try (UnixDirectoryStream stream =
+ new UnixDirectoryStream(dir, ptr, e -> true)) {
+ if (stream.iterator().hasNext()) {
+ throw new DirectoryNotEmptyException(
+ dir.getPathForExceptionMessage());
+ }
+ }
+ } catch (UnixException e) {
+ e.rethrowAsIOException(dir);
+ }
+ }
+
// move file from source to target
static void move(UnixPath source, UnixPath target, CopyOption... options)
throws IOException
@@ -465,6 +481,7 @@
// copy source to target
if (sourceAttrs.isDirectory()) {
+ ensureEmptyDir(source);
copyDirectory(source, sourceAttrs, target, flags);
} else {
if (sourceAttrs.isSymbolicLink()) {
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java Thu Jun 07 15:10:06 2018 +0200
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java Thu Jun 07 07:43:29 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -249,6 +249,17 @@
}
}
+ // throw a DirectoryNotEmpty exception if not empty
+ static void ensureEmptyDir(WindowsPath dir) throws IOException {
+ try (WindowsDirectoryStream dirStream =
+ new WindowsDirectoryStream(dir, (e) -> true)) {
+ if (dirStream.iterator().hasNext()) {
+ throw new DirectoryNotEmptyException(
+ dir.getPathForExceptionMessage());
+ }
+ }
+ }
+
/**
* Move file from source to target
*/
@@ -407,6 +418,7 @@
// create new directory or directory junction
try {
if (sourceAttrs.isDirectory()) {
+ ensureEmptyDir(source);
CreateDirectory(targetPath, 0L);
} else {
String linkTarget = WindowsLinkSupport.readLink(source);
--- a/test/jdk/java/nio/file/Files/CopyAndMove.java Thu Jun 07 15:10:06 2018 +0200
+++ b/test/jdk/java/nio/file/Files/CopyAndMove.java Thu Jun 07 07:43:29 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333 6917021 7006126 6950237 8006645
+ * @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407
* @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed)
* @library .. /test/lib
* @build jdk.test.lib.RandomFactory
@@ -448,6 +448,10 @@
moveAndVerify(source, target);
throw new RuntimeException("IOException expected");
} catch (IOException x) {
+ if (!(x instanceof DirectoryNotEmptyException)) {
+ throw new RuntimeException
+ ("DirectoryNotEmptyException expected", x);
+ }
}
delete(source.resolve("foo"));
delete(source);