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