8201407: Files.move throws DirectoryNonEmptyException when moving directory across file system

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2018-06-07 07:43:29 -07:00
parent 9f39d8c408
commit e9f3b0e527
4 changed files with 41 additions and 7 deletions

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1391,8 +1391,9 @@ public final class Files {
* specific exception)</i> * specific exception)</i>
* @throws DirectoryNotEmptyException * @throws DirectoryNotEmptyException
* the {@code REPLACE_EXISTING} option is specified but the file * the {@code REPLACE_EXISTING} option is specified but the file
* cannot be replaced because it is a non-empty directory * cannot be replaced because it is a non-empty directory, or the
* <i>(optional specific exception)</i> * source is a non-empty directory containing entries that would
* be required to be moved <i>(optional specific exceptions)</i>
* @throws AtomicMoveNotSupportedException * @throws AtomicMoveNotSupportedException
* if the options array contains the {@code ATOMIC_MOVE} option but * if the options array contains the {@code ATOMIC_MOVE} option but
* the file cannot be moved as an atomic file system operation. * the file cannot be moved as an atomic file system operation.

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -373,6 +373,22 @@ class UnixCopyFile {
} }
} }
// 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 // move file from source to target
static void move(UnixPath source, UnixPath target, CopyOption... options) static void move(UnixPath source, UnixPath target, CopyOption... options)
throws IOException throws IOException
@ -465,6 +481,7 @@ class UnixCopyFile {
// copy source to target // copy source to target
if (sourceAttrs.isDirectory()) { if (sourceAttrs.isDirectory()) {
ensureEmptyDir(source);
copyDirectory(source, sourceAttrs, target, flags); copyDirectory(source, sourceAttrs, target, flags);
} else { } else {
if (sourceAttrs.isSymbolicLink()) { if (sourceAttrs.isSymbolicLink()) {

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -249,6 +249,17 @@ class WindowsFileCopy {
} }
} }
// 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 * Move file from source to target
*/ */
@ -407,6 +418,7 @@ class WindowsFileCopy {
// create new directory or directory junction // create new directory or directory junction
try { try {
if (sourceAttrs.isDirectory()) { if (sourceAttrs.isDirectory()) {
ensureEmptyDir(source);
CreateDirectory(targetPath, 0L); CreateDirectory(targetPath, 0L);
} else { } else {
String linkTarget = WindowsLinkSupport.readLink(source); String linkTarget = WindowsLinkSupport.readLink(source);

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*/ */
/* @test /* @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) * @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed)
* @library .. /test/lib * @library .. /test/lib
* @build jdk.test.lib.RandomFactory * @build jdk.test.lib.RandomFactory
@ -448,6 +448,10 @@ public class CopyAndMove {
moveAndVerify(source, target); moveAndVerify(source, target);
throw new RuntimeException("IOException expected"); throw new RuntimeException("IOException expected");
} catch (IOException x) { } catch (IOException x) {
if (!(x instanceof DirectoryNotEmptyException)) {
throw new RuntimeException
("DirectoryNotEmptyException expected", x);
}
} }
delete(source.resolve("foo")); delete(source.resolve("foo"));
delete(source); delete(source);