1 /* 2 * Copyright (c) 2009, 2018, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nio.zipfs; 27 28 import static jdk.nio.zipfs.ZipConstants.*; 29 import static jdk.nio.zipfs.ZipUtils.dosToJavaTime; 30 import static jdk.nio.zipfs.ZipUtils.unixToJavaTime; 31 import static jdk.nio.zipfs.ZipUtils.winToJavaTime; 32 33 import java.nio.file.Paths; 34 import java.util.Collections; 35 import java.util.Map; 36 37 /** 38 * Print all loc and cen headers of the ZIP file 39 * 40 * @author Xueming Shen 41 */ 42 public class ZipInfo { 43 44 public static void main(String[] args) throws Throwable { 45 if (args.length < 1) { 46 print("Usage: java ZipInfo zfname"); 47 } else { 48 Map<String, ?> env = Collections.emptyMap(); 49 ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider() 50 .newFileSystem(Paths.get(args[0]), env)); 51 byte[] cen = zfs.cen; 52 if (cen == null) { 53 print("zip file is empty%n"); 54 return; 55 } 56 int pos = 0; 57 byte[] buf = new byte[1024]; 58 int no = 1; 59 while (pos + CENHDR < cen.length) { 60 print("----------------#%d--------------------%n", no++); 61 printCEN(cen, pos); 62 63 // use size CENHDR as the extra bytes to read, just in case the 64 // loc.extra is bigger than the cen.extra, try to avoid to read 65 // twice 66 long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR; 67 if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) 68 ZipFileSystem.zerror("read loc header failed"); 69 if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) { 70 // have to read the second time; 71 len = LOCHDR + LOCNAM(buf) + LOCEXT(buf); 72 if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) 73 ZipFileSystem.zerror("read loc header failed"); 74 } 75 printLOC(buf); 76 pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos); 77 } 78 zfs.close(); 79 } 80 } 81 82 static void print(String fmt, Object... objs) { 83 System.out.printf(fmt, objs); 84 } 85 86 static void printLOC(byte[] loc) { 87 print("%n"); 88 print("[Local File Header]%n"); 89 print(" Signature : %#010x%n", LOCSIG(loc)); 90 if (LOCSIG(loc) != LOCSIG) { 91 print(" Wrong signature!"); 92 return; 93 } 94 print(" Version : %#6x [%d.%d]%n", 95 LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10); 96 print(" Flag : %#6x%n", LOCFLG(loc)); 97 print(" Method : %#6x%n", LOCHOW(loc)); 98 print(" LastMTime : %#10x [%tc]%n", 99 LOCTIM(loc), dosToJavaTime(LOCTIM(loc))); 100 print(" CRC : %#10x%n", LOCCRC(loc)); 101 print(" CSize : %#10x%n", LOCSIZ(loc)); 102 print(" Size : %#10x%n", LOCLEN(loc)); 103 print(" NameLength : %#6x [%s]%n", 104 LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc))); 105 print(" ExtraLength : %#6x%n", LOCEXT(loc)); 106 if (LOCEXT(loc) != 0) 107 printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc)); 108 } 109 110 static void printCEN(byte[] cen, int off) { 111 print("[Central Directory Header]%n"); 112 print(" Signature : %#010x%n", CENSIG(cen, off)); 113 if (CENSIG(cen, off) != CENSIG) { 114 print(" Wrong signature!"); 115 return; 116 } 117 print(" VerMadeby : %#6x [%d, %d.%d]%n", 118 CENVEM(cen, off), (CENVEM(cen, off) >> 8), 119 (CENVEM(cen, off) & 0xff) / 10, 120 (CENVEM(cen, off) & 0xff) % 10); 121 print(" VerExtract : %#6x [%d.%d]%n", 122 CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10); 123 print(" Flag : %#6x%n", CENFLG(cen, off)); 124 print(" Method : %#6x%n", CENHOW(cen, off)); 125 print(" LastMTime : %#10x [%tc]%n", 126 CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off))); 127 print(" CRC : %#10x%n", CENCRC(cen, off)); 128 print(" CSize : %#10x%n", CENSIZ(cen, off)); 129 print(" Size : %#10x%n", CENLEN(cen, off)); 130 print(" NameLen : %#6x [%s]%n", 131 CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off))); 132 print(" ExtraLen : %#6x%n", CENEXT(cen, off)); 133 if (CENEXT(cen, off) != 0) 134 printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off)); 135 print(" CommentLen : %#6x%n", CENCOM(cen, off)); 136 print(" DiskStart : %#6x%n", CENDSK(cen, off)); 137 print(" Attrs : %#6x%n", CENATT(cen, off)); 138 print(" AttrsEx : %#10x%n", CENATX(cen, off)); 139 print(" LocOff : %#10x%n", CENOFF(cen, off)); 140 141 } 142 143 static long locoff(byte[] cen, int pos) { 144 long locoff = CENOFF(cen, pos); 145 if (locoff == ZIP64_MINVAL) { //ZIP64 146 int off = pos + CENHDR + CENNAM(cen, pos); 147 int end = off + CENEXT(cen, pos); 148 while (off + 4 < end) { 149 int tag = SH(cen, off); 150 int sz = SH(cen, off + 2); 151 if (tag != EXTID_ZIP64) { 152 off += 4 + sz; 153 continue; 154 } 155 off += 4; 156 if (CENLEN(cen, pos) == ZIP64_MINVAL) 157 off += 8; 158 if (CENSIZ(cen, pos) == ZIP64_MINVAL) 159 off += 8; 160 return LL(cen, off); 161 } 162 // should never be here 163 } 164 return locoff; 165 } 166 167 static void printExtra(byte[] extra, int off, int len) { 168 int end = off + len; 169 while (off + 4 <= end) { 170 int tag = SH(extra, off); 171 int sz = SH(extra, off + 2); 172 print(" [tag=0x%04x, sz=%d, data= ", tag, sz); 173 if (off + sz > end) { 174 print(" Error: Invalid extra data, beyond extra length"); 175 break; 176 } 177 off += 4; 178 for (int i = 0; i < sz; i++) 179 print("%02x ", extra[off + i]); 180 print("]%n"); 181 switch (tag) { 182 case EXTID_ZIP64 : 183 print(" ->ZIP64: "); 184 int pos = off; 185 while (pos + 8 <= off + sz) { 186 print(" *0x%x ", LL(extra, pos)); 187 pos += 8; 188 } 189 print("%n"); 190 break; 191 case EXTID_NTFS: 192 print(" ->PKWare NTFS%n"); 193 // 4 bytes reserved 194 if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24) 195 print(" Error: Invalid NTFS sub-tag or subsz"); 196 print(" mtime:%tc%n", 197 winToJavaTime(LL(extra, off + 8))); 198 print(" atime:%tc%n", 199 winToJavaTime(LL(extra, off + 16))); 200 print(" ctime:%tc%n", 201 winToJavaTime(LL(extra, off + 24))); 202 break; 203 case EXTID_EXTT: 204 print(" ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]); 205 pos = off + 1 ; 206 while (pos + 4 <= off + sz) { 207 print(" *%tc%n", 208 unixToJavaTime(LG(extra, pos))); 209 pos += 4; 210 } 211 break; 212 default: 213 print(" ->[tag=%x, size=%d]%n", tag, sz); 214 } 215 off += sz; 216 } 217 } 218 }