| @@ -38,4 +38,9 @@ | |||||
| <touch file="${output}/alpha/beta/gamma/gamma.xml"/> | <touch file="${output}/alpha/beta/gamma/gamma.xml"/> | ||||
| </target> | </target> | ||||
| <target name="symlink-nested-setup" depends="setUp"> | |||||
| <symlink link="${output}/alpha/beta/gamma/beta-link" resource="${output}/alpha/beta"/> | |||||
| <touch file="${output}/alpha/beta/gamma/gamma.xml"/> | |||||
| </target> | |||||
| </project> | </project> | ||||
| @@ -1258,6 +1258,18 @@ public class DirectoryScanner | |||||
| final String name = vpath + newFile; | final String name = vpath + newFile; | ||||
| final TokenizedPath newPath = new TokenizedPath(path, newFile); | final TokenizedPath newPath = new TokenizedPath(path, newFile); | ||||
| final File file = new File(dir, newFile); | final File file = new File(dir, newFile); | ||||
| try { | |||||
| // check if it's a filesystem "loop" due to symbolic links | |||||
| if (FileUtils.getFileUtils().isLeadingPath(file.getAbsoluteFile(), | |||||
| dir.getAbsoluteFile(), true)) { | |||||
| continue; | |||||
| } | |||||
| } catch (IOException e) { | |||||
| System.err.println("Failed to determine if " + file + " causes a " + | |||||
| "filesystem loop due to symbolic link; continuing"); | |||||
| } | |||||
| final String[] children = file.list(); | final String[] children = file.list(); | ||||
| if (children == null || (children.length == 0 && file.isFile())) { | if (children == null || (children.length == 0 && file.isFile())) { | ||||
| if (isIncluded(newPath)) { | if (isIncluded(newPath)) { | ||||
| @@ -19,6 +19,7 @@ | |||||
| package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | |||||
| import java.util.Arrays; | import java.util.Arrays; | ||||
| import java.util.Comparator; | import java.util.Comparator; | ||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| @@ -771,7 +772,19 @@ public class Delete extends MatchingTask { | |||||
| } | } | ||||
| for (String s : list) { | for (String s : list) { | ||||
| File f = new File(d, s); | File f = new File(d, s); | ||||
| if (f.isDirectory()) { | |||||
| boolean isFsLoop = false; | |||||
| try { | |||||
| isFsLoop = SYMLINK_UTILS.isSymbolicLink(f) && | |||||
| FileUtils.getFileUtils().isLeadingPath(f.getAbsoluteFile(), | |||||
| d.getAbsoluteFile(), true); | |||||
| } catch (IOException e) { | |||||
| log("Failed to check if " + f + " causes a filesystem loop due to " + | |||||
| "symbolic link; continuing"); | |||||
| } | |||||
| if (f.isDirectory() && !isFsLoop) { | |||||
| removeDir(f); | removeDir(f); | ||||
| } else { | } else { | ||||
| log("Deleting " + f.getAbsolutePath(), quiet ? Project.MSG_VERBOSE : verbosity); | log("Deleting " + f.getAbsolutePath(), quiet ? Project.MSG_VERBOSE : verbosity); | ||||
| @@ -132,6 +132,20 @@ public class DirectoryScannerTest { | |||||
| new String[] {"alpha/beta/gamma"}); | new String[] {"alpha/beta/gamma"}); | ||||
| } | } | ||||
| @Test | |||||
| public void testAllowRecursiveSymlinks() { | |||||
| assumeTrue("Current system does not support Symlinks", supportsSymlinks); | |||||
| buildRule.getProject().executeTarget("symlink-nested-setup"); | |||||
| DirectoryScanner ds = new DirectoryScanner(); | |||||
| ds.setBasedir(new File(buildRule.getProject().getProperty("output"))); | |||||
| ds.setIncludes(new String[] {"alpha/beta/gamma/"}); | |||||
| ds.scan(); | |||||
| compareFiles(ds, new String[] {"alpha/beta/gamma/gamma.xml"}, | |||||
| new String[] {"alpha/beta/gamma"}); | |||||
| } | |||||
| @Test | @Test | ||||
| public void testProhibitSymlinks() { | public void testProhibitSymlinks() { | ||||
| assumeTrue("Current system does not support Symlinks", supportsSymlinks); | assumeTrue("Current system does not support Symlinks", supportsSymlinks); | ||||