1 /*
2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25    @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977 8186464
26    @summary Make sure we can read a zip file.
27    @key randomness
28    @modules jdk.zipfs
29  */
30 
31 import java.io.*;
32 import java.net.URI;
33 import java.nio.file.Files;
34 import java.nio.file.FileSystem;
35 import java.nio.file.FileSystems;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.nio.file.NoSuchFileException;
39 import java.nio.file.StandardCopyOption;
40 import java.nio.file.StandardOpenOption;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.zip.*;
44 
45 import static java.nio.charset.StandardCharsets.US_ASCII;
46 
47 public class ReadZip {
unreached(Object o)48     private static void unreached (Object o)
49         throws Exception
50     {
51         // Should never get here
52         throw new Exception ("Expected exception was not thrown");
53     }
54 
main(String args[])55     public static void main(String args[]) throws Exception {
56         try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."),
57                                                "input.zip"))) {
58             // Make sure we throw NPE on null objects
59             try { unreached (zf.getEntry(null)); }
60             catch (NullPointerException e) {}
61 
62             try { unreached (zf.getInputStream(null)); }
63             catch (NullPointerException e) {}
64 
65             ZipEntry ze = zf.getEntry("ReadZip.java");
66             if (ze == null) {
67                 throw new Exception("cannot read from zip file");
68             }
69         }
70 
71         // Make sure we can read the zip file that has some garbage
72         // bytes padded at the end.
73         File newZip = new File(System.getProperty("test.dir", "."), "input2.zip");
74         Files.copy(Paths.get(System.getProperty("test.src", ""), "input.zip"),
75                    newZip.toPath(), StandardCopyOption.REPLACE_EXISTING);
76 
77         newZip.setWritable(true);
78 
79         // pad some bytes
80         try (OutputStream os = Files.newOutputStream(newZip.toPath(),
81                                                      StandardOpenOption.APPEND)) {
82             os.write(1); os.write(3); os.write(5); os.write(7);
83         }
84 
85         try (ZipFile zf = new ZipFile(newZip)) {
86             ZipEntry ze = zf.getEntry("ReadZip.java");
87             if (ze == null) {
88                 throw new Exception("cannot read from zip file");
89             }
90         } finally {
91             newZip.delete();
92         }
93 
94         // Read zip file comment
95         try {
96             try (FileOutputStream fos = new FileOutputStream(newZip);
97                  ZipOutputStream zos = new ZipOutputStream(fos))
98             {
99                 ZipEntry ze = new ZipEntry("ZipEntry");
100                 zos.putNextEntry(ze);
101                 zos.write(1); zos.write(2); zos.write(3); zos.write(4);
102                 zos.closeEntry();
103                 zos.setComment("This is the comment for testing");
104             }
105 
106             try (ZipFile zf = new ZipFile(newZip)) {
107                 ZipEntry ze = zf.getEntry("ZipEntry");
108                 if (ze == null)
109                     throw new Exception("cannot read entry from zip file");
110                 if (!"This is the comment for testing".equals(zf.getComment()))
111                     throw new Exception("cannot read comment from zip file");
112             }
113         } finally {
114             newZip.delete();
115         }
116 
117         // Read directory entry
118         try {
119             try (FileOutputStream fos = new FileOutputStream(newZip);
120                  ZipOutputStream zos = new ZipOutputStream(fos))
121             {
122                 ZipEntry ze = new ZipEntry("directory/");
123                 zos.putNextEntry(ze);
124                 zos.closeEntry();
125             }
126             try (ZipFile zf = new ZipFile(newZip)) {
127                 ZipEntry ze = zf.getEntry("directory/");
128                 if (ze == null || !ze.isDirectory())
129                     throw new RuntimeException("read entry \"directory/\" failed");
130                 try (InputStream is = zf.getInputStream(ze)) {
131                     is.available();
132                 } catch (Exception x) {
133                     x.printStackTrace();
134                 }
135 
136                 ze = zf.getEntry("directory");
137                 if (ze == null || !ze.isDirectory())
138                     throw new RuntimeException("read entry \"directory\" failed");
139                 try (InputStream is = zf.getInputStream(ze)) {
140                     is.available();
141                 } catch (Exception x) {
142                     x.printStackTrace();
143                 }
144             }
145         } finally {
146             newZip.delete();
147         }
148 
149         // Throw a FNF exception when read a non-existing zip file
150         try { unreached (new ZipFile(
151                              new File(System.getProperty("test.src", "."),
152                                      "input"
153                                       + String.valueOf(new java.util.Random().nextInt())
154                                       + ".zip")));
155         } catch (NoSuchFileException nsfe) {}
156 
157         // read a zip file with ZIP64 end
158         Path path = Paths.get(System.getProperty("test.dir", ""), "end64.zip");
159         try {
160             URI uri = URI.create("jar:" + path.toUri());
161             Map<String, Object> env = Map.of("create", "true", "forceZIP64End", "true");
162             try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
163                 Files.write(fs.getPath("hello"), "hello".getBytes());
164             }
165             try (ZipFile zf = new ZipFile(path.toFile())) {
166                 if (!"hello".equals(new String(zf.getInputStream(new ZipEntry("hello"))
167                                                .readAllBytes(),
168                                                US_ASCII)))
169                     throw new RuntimeException("zipfile: read entry failed");
170             } catch (IOException x) {
171                 throw new RuntimeException("zipfile: zip64 end failed");
172             }
173             try (FileSystem fs = FileSystems.newFileSystem(uri, Map.of())) {
174                 if (!"hello".equals(new String(Files.readAllBytes(fs.getPath("hello")))))
175                     throw new RuntimeException("zipfs: read entry failed");
176             } catch (IOException x) {
177                 throw new RuntimeException("zipfile: zip64 end failed");
178             }
179         } finally {
180             Files.deleteIfExists(path);
181         }
182 
183         // read a zip file created via "echo hello | zip dst.zip -", which uses
184         // ZIP64 end record
185         if (Files.notExists(Paths.get("/usr/bin/zip")))
186             return;
187         try {
188             Process zip = new ProcessBuilder("zip", path.toString().toString(), "-").start();
189             OutputStream os = zip.getOutputStream();
190             os.write("hello".getBytes(US_ASCII));
191             os.close();
192             zip.waitFor();
193             if (zip.exitValue() == 0 && Files.exists(path)) {
194                 try (ZipFile zf = new ZipFile(path.toFile())) {
195                     if (!"hello".equals(new String(zf.getInputStream(new ZipEntry("-"))
196                                                        .readAllBytes())))
197                         throw new RuntimeException("zipfile: read entry failed");
198                 } catch (IOException x) {
199                     throw new RuntimeException("zipfile: zip64 end failed");
200                 }
201             }
202         } finally {
203             Files.deleteIfExists(path);
204         }
205     }
206 }
207