# HG changeset patch # Parent 837bba5fec5b7695a4652fbccf374a5bc1f903c4 diff --git a/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjSymlinkTest.java b/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjSymlinkTest.java --- a/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjSymlinkTest.java +++ b/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjSymlinkTest.java @@ -278,6 +278,52 @@ return false; } + /** + * Test that copy operations skips recursive symbolic links. See bug 225991. + * + * Use this directory tree for testing. + *
+ * - source + * - a + * - b (symbolic link to a) + * - c + * - data.txt + * - target + *+ * + * @throws java.io.IOException + */ + public void testCopySkipsRecursiveSymlinks() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + FileObject dirFO = FileUtil.toFileObject(dir); + File source, a, b = null, c, dataTxt; + try { + source = new File(dir, "source"); + a = new File(source, "a"); + b = new File(a, "b"); + c = new File(source, "c"); + dataTxt = new File(c, "data.txt"); + a.mkdirs(); + c.mkdir(); + dataTxt.createNewFile(); + Files.createSymbolicLink(b.toPath(), a.toPath()); + + dirFO.refresh(); + dirFO.getFileObject("source").copy(dirFO, "target", null); + + assertNotNull(dirFO.getFileObject("target/a")); + assertNotNull(dirFO.getFileObject("target/c/data.txt")); + assertNull(dirFO.getFileObject("target/a/b")); + } finally { + if (b != null) { + b.delete(); + } + } + } + private void printSkipping() { System.out.println( "Symbolic links are not supported, skipping test " + getName()); diff --git a/openide.filesystems/src/org/openide/filesystems/FileObject.java b/openide.filesystems/src/org/openide/filesystems/FileObject.java --- a/openide.filesystems/src/org/openide/filesystems/FileObject.java +++ b/openide.filesystems/src/org/openide/filesystems/FileObject.java @@ -147,7 +147,12 @@ FileObject peer = target.createFolder(name); FileUtil.copyAttributes(this, peer); for (FileObject fo : getChildren()) { - fo.copy(peer, fo.getName(), fo.getExt()); + if (fo.isData() || !fo.isRecursiveSymbolicLink()) { + fo.copy(peer, fo.getName(), fo.getExt()); + } else { + ExternalUtil.LOG.log(Level.INFO, + "Skipping recursive symlink {0}", fo); //NOI18N + } } return peer; } diff --git a/openide.loaders/nbproject/project.xml b/openide.loaders/nbproject/project.xml --- a/openide.loaders/nbproject/project.xml +++ b/openide.loaders/nbproject/project.xml @@ -122,7 +122,7 @@
+ * - source + * - a + * - b (symbolic link to a) + * - c + * - data.txt + * - target + *+ * @throws java.io.IOException + */ + public void testCopySkipsRecursiveSymlinks() throws IOException { + File dir = getWorkDir(); + FileObject dirFO = FileUtil.toFileObject(dir); + File source, target, a, b = null, c, dataTxt; + try { + source = new File(dir, "source"); + a = new File(source, "a"); + b = new File(a, "b"); + c = new File(source, "c"); + dataTxt = new File(c, "data.txt"); + target = new File(dir, "target"); + a.mkdirs(); + c.mkdir(); + target.mkdir(); + dataTxt.createNewFile(); + try { + Files.createSymbolicLink(b.toPath(), a.toPath()); + } catch (IOException e) { + System.out.println("Skipping test " + getName() + + ", symlinks are not supported."); + return; + } + dirFO.refresh(); + DataObject sourceDOB = DataObject.find(dirFO.getFileObject("source")); + DataObject targetDOB = DataObject.find(dirFO.getFileObject("target")); + sourceDOB.copy((DataFolder) targetDOB); + assertNotNull(dirFO.getFileObject("target/source/a")); + assertNotNull(dirFO.getFileObject("target/source/c/data.txt")); + assertNull(dirFO.getFileObject("target/source/a/b")); + } finally { + if (b != null) { + b.delete(); + } + } + } + + /** + * Recursively delete all symbolic links in a directory. It's safer to call + * this method before {@link #clearWorkDir()} if there is risk that some + * tests can leave (recursive) symbolic links in workdir. + */ + private void clearSymlinks(File root) { + for (File f : root.listFiles()) { + if (Files.isSymbolicLink(f.toPath())) { + f.delete(); + } else if (f.isDirectory()) { + clearSymlinks(f); + } + } + } }