8211385: (zipfs) ZipDirectoryStream yields a stream of absolute paths when directory is relative jdk-12+14
authorsherman
Wed, 03 Oct 2018 12:54:54 -0700
changeset 52008 6f04692c7d51
parent 52007 b16820c2336d
child 52009 35511492cd6d
8211385: (zipfs) ZipDirectoryStream yields a stream of absolute paths when directory is relative Reviewed-by: alanb, lancea
src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java
src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
test/jdk/jdk/nio/zipfs/Basic.java
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java	Wed Oct 03 19:30:49 2018 +0000
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java	Wed Oct 03 12:54:54 2018 -0700
@@ -41,21 +41,21 @@
 class ZipDirectoryStream implements DirectoryStream<Path> {
 
     private final ZipFileSystem zipfs;
-    private final byte[] path;
+    private final ZipPath dir;
     private final DirectoryStream.Filter<? super Path> filter;
     private volatile boolean isClosed;
     private volatile Iterator<Path> itr;
 
-    ZipDirectoryStream(ZipPath zipPath,
+    ZipDirectoryStream(ZipPath dir,
                        DirectoryStream.Filter<? super java.nio.file.Path> filter)
         throws IOException
     {
-        this.zipfs = zipPath.getFileSystem();
-        this.path = zipPath.getResolvedPath();
+        this.zipfs = dir.getFileSystem();
+        this.dir = dir;
         this.filter = filter;
         // sanity check
-        if (!zipfs.isDirectory(path))
-            throw new NotDirectoryException(zipPath.toString());
+        if (!zipfs.isDirectory(dir.getResolvedPath()))
+            throw new NotDirectoryException(dir.toString());
     }
 
     @Override
@@ -66,7 +66,7 @@
             throw new IllegalStateException("Iterator has already been returned");
 
         try {
-            itr = zipfs.iteratorOf(path, filter);
+            itr = zipfs.iteratorOf(dir, filter);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
@@ -98,5 +98,4 @@
         isClosed = true;
     }
 
-
 }
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Wed Oct 03 19:30:49 2018 +0000
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Wed Oct 03 12:54:54 2018 -0700
@@ -399,23 +399,32 @@
     }
 
     // returns the list of child paths of "path"
-    Iterator<Path> iteratorOf(byte[] path,
+    Iterator<Path> iteratorOf(ZipPath dir,
                               DirectoryStream.Filter<? super Path> filter)
         throws IOException
     {
         beginWrite();    // iteration of inodes needs exclusive lock
         try {
             ensureOpen();
+            byte[] path = dir.getResolvedPath();
             IndexNode inode = getInode(path);
             if (inode == null)
                 throw new NotDirectoryException(getString(path));
             List<Path> list = new ArrayList<>();
             IndexNode child = inode.child;
             while (child != null) {
-                // assume all path from zip file itself is "normalized"
-                ZipPath zp = new ZipPath(this, child.name, true);
-                if (filter == null || filter.accept(zp))
-                    list.add(zp);
+                // (1) assume all path from zip file itself is "normalized"
+                // (2) IndexNode.name is absolute. see IndexNode(byte[],int,int)
+                // (3) if parent "dir" is relative when ZipDirectoryStream
+                //     is created, the returned child path needs to be relative
+                //     as well.
+                byte[] cname = child.name;
+                if (!dir.isAbsolute()) {
+                    cname = Arrays.copyOfRange(cname, 1, cname.length);
+                }
+                ZipPath zpath = new ZipPath(this, cname, true);
+                if (filter == null || filter.accept(zpath))
+                    list.add(zpath);
                 child = child.sibling;
             }
             return list.iterator();
--- a/test/jdk/jdk/nio/zipfs/Basic.java	Wed Oct 03 19:30:49 2018 +0000
+++ b/test/jdk/jdk/nio/zipfs/Basic.java	Wed Oct 03 12:54:54 2018 -0700
@@ -43,7 +43,7 @@
 import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
 /**
  * @test
- * @bug 8038500 8040059 8150366 8150496 8147539
+ * @bug 8038500 8040059 8150366 8150496 8147539 8211385
  * @summary Basic test for zip provider
  *
  * @modules jdk.zipfs
@@ -89,16 +89,30 @@
 
         // Test: DirectoryStream
         found = false;
+
         try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
             for (Path entry: stream) {
                 found = entry.toString().equals("/META-INF");
                 if (found) break;
             }
         }
-
         if (!found)
             throw new RuntimeException("Expected file not found");
 
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("META-INF"))) {
+            for (Path entry: stream) {
+                if (entry.toString().equals("/META-INF/services"))
+                    throw new RuntimeException("child path should be relative");
+            }
+        }
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/META-INF"))) {
+            for (Path entry: stream) {
+                if (entry.toString().equals("META-INF/services"))
+                    throw new RuntimeException("child path should be absolute");
+            }
+        }
+
         // Test: copy file from zip file to current (scratch) directory
         Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
         if (Files.exists(source)) {
@@ -133,6 +147,8 @@
         try {
             fs.provider().checkAccess(fs.getPath("/missing"), AccessMode.READ);
         } catch (ClosedFileSystemException x) { }
+
+        Files.deleteIfExists(jarFile);
     }
 
     // FileVisitor that pretty prints a file tree