< prev index next >

src/java.base/share/classes/java/util/zip/ZipFile.java

Print this page
8203328: Rename EFS in java.util.zip internals to something meaningful
Reviewed-by: sherman


 360      * Closing this ZIP file will, in turn, close all input streams that
 361      * have been returned by invocations of this method.
 362      *
 363      * @param entry the zip file entry
 364      * @return the input stream for reading the contents of the specified
 365      * zip file entry.
 366      * @throws ZipException if a ZIP format error has occurred
 367      * @throws IOException if an I/O error has occurred
 368      * @throws IllegalStateException if the zip file has been closed
 369      */
 370     public InputStream getInputStream(ZipEntry entry) throws IOException {
 371         Objects.requireNonNull(entry, "entry");
 372         int pos = -1;
 373         ZipFileInputStream in;
 374         Source zsrc = res.zsrc;
 375         Set<InputStream> istreams = res.istreams;
 376         synchronized (this) {
 377             ensureOpen();
 378             if (Objects.equals(lastEntryName, entry.name)) {
 379                 pos = lastEntryPos;
 380             } else if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
 381                 pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false);
 382             } else {
 383                 pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
 384             }
 385             if (pos == -1) {
 386                 return null;
 387             }
 388             in = new ZipFileInputStream(zsrc.cen, pos);
 389             switch (CENHOW(zsrc.cen, pos)) {
 390             case STORED:
 391                 synchronized (istreams) {
 392                     istreams.add(in);
 393                 }
 394                 return in;
 395             case DEFLATED:
 396                 // Inflater likes a bit of slack
 397                 // MORE: Compute good size for inflater stream:
 398                 long size = CENLEN(zsrc.cen, pos) + 2;
 399                 if (size > 65536) {
 400                     size = 8192;


 588      * Returns an ordered {@code Stream} over the ZIP file entries.
 589      *
 590      * Entries appear in the {@code Stream} in the order they appear in
 591      * the central directory of the ZIP file.
 592      *
 593      * @return an ordered {@code Stream} of entries in this ZIP file
 594      * @throws IllegalStateException if the zip file has been closed
 595      * @since 1.8
 596      */
 597     public Stream<? extends ZipEntry> stream() {
 598         synchronized (this) {
 599             ensureOpen();
 600             return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
 601                 pos -> getZipEntry(null, null, pos, ZipEntry::new)), false);
 602        }
 603     }
 604 
 605     private String getEntryName(int pos) {
 606         byte[] cen = res.zsrc.cen;
 607         int nlen = CENNAM(cen, pos);
 608         if (!zc.isUTF8() && (CENFLG(cen, pos) & EFS) != 0) {
 609             return zc.toStringUTF8(cen, pos + CENHDR, nlen);
 610         } else {
 611             return zc.toString(cen, pos + CENHDR, nlen);
 612         }
 613     }
 614 
 615     /*
 616      * Returns an ordered {@code Stream} over the zip file entry names.
 617      *
 618      * Entry names appear in the {@code Stream} in the order they appear in
 619      * the central directory of the ZIP file.
 620      *
 621      * @return an ordered {@code Stream} of entry names in this zip file
 622      * @throws IllegalStateException if the zip file has been closed
 623      * @since 10
 624      */
 625     private Stream<String> entryNameStream() {
 626         synchronized (this) {
 627             ensureOpen();
 628             return StreamSupport.stream(


 648                 pos -> (JarEntry)getZipEntry(null, null, pos, func)), false);
 649         }
 650     }
 651 
 652     private String lastEntryName;
 653     private int lastEntryPos;
 654 
 655     /* Checks ensureOpen() before invoke this method */
 656     private ZipEntry getZipEntry(String name, byte[] bname, int pos,
 657                                  Function<String, ? extends ZipEntry> func) {
 658         byte[] cen = res.zsrc.cen;
 659         int nlen = CENNAM(cen, pos);
 660         int elen = CENEXT(cen, pos);
 661         int clen = CENCOM(cen, pos);
 662         int flag = CENFLG(cen, pos);
 663         if (name == null || bname.length != nlen) {
 664             // to use the entry name stored in cen, if the passed in name is
 665             // (1) null, invoked from iterator, or
 666             // (2) not equal to the name stored, a slash is appended during
 667             // getEntryPos() search.
 668             if (!zc.isUTF8() && (flag & EFS) != 0) {
 669                 name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
 670             } else {
 671                 name = zc.toString(cen, pos + CENHDR, nlen);
 672             }
 673         }
 674         ZipEntry e = func.apply(name);    //ZipEntry e = new ZipEntry(name);
 675         e.flag = flag;
 676         e.xdostime = CENTIM(cen, pos);
 677         e.crc = CENCRC(cen, pos);
 678         e.size = CENLEN(cen, pos);
 679         e.csize = CENSIZ(cen, pos);
 680         e.method = CENHOW(cen, pos);
 681         if (elen != 0) {
 682             int start = pos + CENHDR + nlen;
 683             e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
 684         }
 685         if (clen != 0) {
 686             int start = pos + CENHDR + nlen + elen;
 687             if (!zc.isUTF8() && (flag & EFS) != 0) {
 688                 e.comment = zc.toStringUTF8(cen, start, clen);
 689             } else {
 690                 e.comment = zc.toString(cen, start, clen);
 691             }
 692         }
 693         lastEntryName = e.name;
 694         lastEntryPos = pos;
 695         return e;
 696     }
 697 
 698     /**
 699      * Returns the number of entries in the ZIP file.
 700      *
 701      * @return the number of entries in the ZIP file
 702      * @throws IllegalStateException if the zip file has been closed
 703      */
 704     public int size() {
 705         synchronized (this) {
 706             ensureOpen();
 707             return res.zsrc.total;


 967                     if (rem == ZIP64_MAGICVAL) {
 968                         if (sz < 8 || (off + 8) > end)
 969                             break;
 970                         rem = get64(cen, off);
 971                         sz -= 8;
 972                         off += 8;
 973                     }
 974                     if (pos == ZIP64_MAGICVAL) {
 975                         if (sz < 8 || (off + 8) > end)
 976                             break;
 977                         pos = get64(cen, off);
 978                         sz -= 8;
 979                         off += 8;
 980                     }
 981                     break;
 982                 }
 983                 off += sz;
 984             }
 985         }
 986 
 987        /* The Zip file spec explicitly allows the LOC extra data size to

 988         * be different from the CEN extra data size. Since we cannot trust
 989         * the CEN extra data size, we need to read the LOC to determine
 990         * the entry data offset.
 991         */
 992         private long initDataOffset() throws IOException {
 993             if (pos <= 0) {
 994                 byte[] loc = new byte[LOCHDR];
 995                 pos = -pos;
 996                 int len = ZipFile.this.res.zsrc.readFullyAt(loc, 0, loc.length, pos);
 997                 if (len != LOCHDR) {
 998                     throw new ZipException("ZipFile error reading zip file");
 999                 }
1000                 if (LOCSIG(loc) != LOCSIG) {
1001                     throw new ZipException("ZipFile invalid LOC header (bad signature)");
1002                 }
1003                 pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1004             }
1005             return pos;
1006         }
1007 


1272                 try {
1273                     this.zfile.close();
1274                 } catch (IOException xx) {}
1275                 throw x;
1276             }
1277         }
1278 
1279         private void close() throws IOException {
1280             zfile.close();
1281             zfile = null;
1282             cen = null;
1283             entries = null;
1284             table = null;
1285             metanames = null;
1286         }
1287 
1288         private static final int BUF_SIZE = 8192;
1289         private final int readFullyAt(byte[] buf, int off, int len, long pos)
1290             throws IOException
1291         {
1292             synchronized(zfile) {
1293                 zfile.seek(pos);
1294                 int N = len;
1295                 while (N > 0) {
1296                     int n = Math.min(BUF_SIZE, N);
1297                     zfile.readFully(buf, off, n);
1298                     off += n;
1299                     N -= n;
1300                 }
1301                 return len;
1302             }
1303         }
1304 
1305         private final int readAt(byte[] buf, int off, int len, long pos)
1306             throws IOException
1307         {
1308             synchronized(zfile) {
1309                 zfile.seek(pos);
1310                 return zfile.read(buf, off, len);
1311             }
1312         }
1313 
1314         private static final int hashN(byte[] a, int off, int len) {
1315             int h = 1;
1316             while (len-- > 0) {
1317                 h = 31 * h + a[off++];
1318             }
1319             return h;
1320         }
1321 
1322         private static final int hash_append(int hash, byte b) {
1323             return hash * 31 + b;
1324         }
1325 
1326         private static class End {
1327             int  centot;     // 4 bytes
1328             long cenlen;     // 4 bytes


1527         private static void zerror(String msg) throws ZipException {
1528             throw new ZipException(msg);
1529         }
1530 
1531         /*
1532          * Returns the {@code pos} of the zip cen entry corresponding to the
1533          * specified entry name, or -1 if not found.
1534          */
1535         private int getEntryPos(byte[] name, boolean addSlash) {
1536             if (total == 0) {
1537                 return -1;
1538             }
1539             int hsh = hashN(name, 0, name.length);
1540             int idx = table[(hsh & 0x7fffffff) % tablelen];
1541             /*
1542              * This while loop is an optimization where a double lookup
1543              * for name and name+/ is being performed. The name char
1544              * array has enough room at the end to try again with a
1545              * slash appended if the first table lookup does not succeed.
1546              */
1547             while(true) {
1548                 /*
1549                  * Search down the target hash chain for a entry whose
1550                  * 32 bit hash matches the hashed name.
1551                  */
1552                 while (idx != ZIP_ENDCHAIN) {
1553                     if (getEntryHash(idx) == hsh) {
1554                         // The CEN name must match the specfied one
1555                         int pos = getEntryPos(idx);
1556                         if (name.length == CENNAM(cen, pos)) {
1557                             boolean matched = true;
1558                             int nameoff = pos + CENHDR;
1559                             for (int i = 0; i < name.length; i++) {
1560                                 if (name[i] != cen[nameoff++]) {
1561                                     matched = false;
1562                                     break;
1563                                 }
1564                             }
1565                             if (matched) {
1566                                 return pos;
1567                             }




 360      * Closing this ZIP file will, in turn, close all input streams that
 361      * have been returned by invocations of this method.
 362      *
 363      * @param entry the zip file entry
 364      * @return the input stream for reading the contents of the specified
 365      * zip file entry.
 366      * @throws ZipException if a ZIP format error has occurred
 367      * @throws IOException if an I/O error has occurred
 368      * @throws IllegalStateException if the zip file has been closed
 369      */
 370     public InputStream getInputStream(ZipEntry entry) throws IOException {
 371         Objects.requireNonNull(entry, "entry");
 372         int pos = -1;
 373         ZipFileInputStream in;
 374         Source zsrc = res.zsrc;
 375         Set<InputStream> istreams = res.istreams;
 376         synchronized (this) {
 377             ensureOpen();
 378             if (Objects.equals(lastEntryName, entry.name)) {
 379                 pos = lastEntryPos;
 380             } else if (!zc.isUTF8() && (entry.flag & USE_UTF8) != 0) {
 381                 pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false);
 382             } else {
 383                 pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
 384             }
 385             if (pos == -1) {
 386                 return null;
 387             }
 388             in = new ZipFileInputStream(zsrc.cen, pos);
 389             switch (CENHOW(zsrc.cen, pos)) {
 390             case STORED:
 391                 synchronized (istreams) {
 392                     istreams.add(in);
 393                 }
 394                 return in;
 395             case DEFLATED:
 396                 // Inflater likes a bit of slack
 397                 // MORE: Compute good size for inflater stream:
 398                 long size = CENLEN(zsrc.cen, pos) + 2;
 399                 if (size > 65536) {
 400                     size = 8192;


 588      * Returns an ordered {@code Stream} over the ZIP file entries.
 589      *
 590      * Entries appear in the {@code Stream} in the order they appear in
 591      * the central directory of the ZIP file.
 592      *
 593      * @return an ordered {@code Stream} of entries in this ZIP file
 594      * @throws IllegalStateException if the zip file has been closed
 595      * @since 1.8
 596      */
 597     public Stream<? extends ZipEntry> stream() {
 598         synchronized (this) {
 599             ensureOpen();
 600             return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
 601                 pos -> getZipEntry(null, null, pos, ZipEntry::new)), false);
 602        }
 603     }
 604 
 605     private String getEntryName(int pos) {
 606         byte[] cen = res.zsrc.cen;
 607         int nlen = CENNAM(cen, pos);
 608         if (!zc.isUTF8() && (CENFLG(cen, pos) & USE_UTF8) != 0) {
 609             return zc.toStringUTF8(cen, pos + CENHDR, nlen);
 610         } else {
 611             return zc.toString(cen, pos + CENHDR, nlen);
 612         }
 613     }
 614 
 615     /*
 616      * Returns an ordered {@code Stream} over the zip file entry names.
 617      *
 618      * Entry names appear in the {@code Stream} in the order they appear in
 619      * the central directory of the ZIP file.
 620      *
 621      * @return an ordered {@code Stream} of entry names in this zip file
 622      * @throws IllegalStateException if the zip file has been closed
 623      * @since 10
 624      */
 625     private Stream<String> entryNameStream() {
 626         synchronized (this) {
 627             ensureOpen();
 628             return StreamSupport.stream(


 648                 pos -> (JarEntry)getZipEntry(null, null, pos, func)), false);
 649         }
 650     }
 651 
 652     private String lastEntryName;
 653     private int lastEntryPos;
 654 
 655     /* Checks ensureOpen() before invoke this method */
 656     private ZipEntry getZipEntry(String name, byte[] bname, int pos,
 657                                  Function<String, ? extends ZipEntry> func) {
 658         byte[] cen = res.zsrc.cen;
 659         int nlen = CENNAM(cen, pos);
 660         int elen = CENEXT(cen, pos);
 661         int clen = CENCOM(cen, pos);
 662         int flag = CENFLG(cen, pos);
 663         if (name == null || bname.length != nlen) {
 664             // to use the entry name stored in cen, if the passed in name is
 665             // (1) null, invoked from iterator, or
 666             // (2) not equal to the name stored, a slash is appended during
 667             // getEntryPos() search.
 668             if (!zc.isUTF8() && (flag & USE_UTF8) != 0) {
 669                 name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
 670             } else {
 671                 name = zc.toString(cen, pos + CENHDR, nlen);
 672             }
 673         }
 674         ZipEntry e = func.apply(name);    //ZipEntry e = new ZipEntry(name);
 675         e.flag = flag;
 676         e.xdostime = CENTIM(cen, pos);
 677         e.crc = CENCRC(cen, pos);
 678         e.size = CENLEN(cen, pos);
 679         e.csize = CENSIZ(cen, pos);
 680         e.method = CENHOW(cen, pos);
 681         if (elen != 0) {
 682             int start = pos + CENHDR + nlen;
 683             e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
 684         }
 685         if (clen != 0) {
 686             int start = pos + CENHDR + nlen + elen;
 687             if (!zc.isUTF8() && (flag & USE_UTF8) != 0) {
 688                 e.comment = zc.toStringUTF8(cen, start, clen);
 689             } else {
 690                 e.comment = zc.toString(cen, start, clen);
 691             }
 692         }
 693         lastEntryName = e.name;
 694         lastEntryPos = pos;
 695         return e;
 696     }
 697 
 698     /**
 699      * Returns the number of entries in the ZIP file.
 700      *
 701      * @return the number of entries in the ZIP file
 702      * @throws IllegalStateException if the zip file has been closed
 703      */
 704     public int size() {
 705         synchronized (this) {
 706             ensureOpen();
 707             return res.zsrc.total;


 967                     if (rem == ZIP64_MAGICVAL) {
 968                         if (sz < 8 || (off + 8) > end)
 969                             break;
 970                         rem = get64(cen, off);
 971                         sz -= 8;
 972                         off += 8;
 973                     }
 974                     if (pos == ZIP64_MAGICVAL) {
 975                         if (sz < 8 || (off + 8) > end)
 976                             break;
 977                         pos = get64(cen, off);
 978                         sz -= 8;
 979                         off += 8;
 980                     }
 981                     break;
 982                 }
 983                 off += sz;
 984             }
 985         }
 986 
 987         /*
 988          * The Zip file spec explicitly allows the LOC extra data size to
 989          * be different from the CEN extra data size. Since we cannot trust
 990          * the CEN extra data size, we need to read the LOC to determine
 991          * the entry data offset.
 992          */
 993         private long initDataOffset() throws IOException {
 994             if (pos <= 0) {
 995                 byte[] loc = new byte[LOCHDR];
 996                 pos = -pos;
 997                 int len = ZipFile.this.res.zsrc.readFullyAt(loc, 0, loc.length, pos);
 998                 if (len != LOCHDR) {
 999                     throw new ZipException("ZipFile error reading zip file");
1000                 }
1001                 if (LOCSIG(loc) != LOCSIG) {
1002                     throw new ZipException("ZipFile invalid LOC header (bad signature)");
1003                 }
1004                 pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1005             }
1006             return pos;
1007         }
1008 


1273                 try {
1274                     this.zfile.close();
1275                 } catch (IOException xx) {}
1276                 throw x;
1277             }
1278         }
1279 
1280         private void close() throws IOException {
1281             zfile.close();
1282             zfile = null;
1283             cen = null;
1284             entries = null;
1285             table = null;
1286             metanames = null;
1287         }
1288 
1289         private static final int BUF_SIZE = 8192;
1290         private final int readFullyAt(byte[] buf, int off, int len, long pos)
1291             throws IOException
1292         {
1293             synchronized (zfile) {
1294                 zfile.seek(pos);
1295                 int N = len;
1296                 while (N > 0) {
1297                     int n = Math.min(BUF_SIZE, N);
1298                     zfile.readFully(buf, off, n);
1299                     off += n;
1300                     N -= n;
1301                 }
1302                 return len;
1303             }
1304         }
1305 
1306         private final int readAt(byte[] buf, int off, int len, long pos)
1307             throws IOException
1308         {
1309             synchronized (zfile) {
1310                 zfile.seek(pos);
1311                 return zfile.read(buf, off, len);
1312             }
1313         }
1314 
1315         private static final int hashN(byte[] a, int off, int len) {
1316             int h = 1;
1317             while (len-- > 0) {
1318                 h = 31 * h + a[off++];
1319             }
1320             return h;
1321         }
1322 
1323         private static final int hash_append(int hash, byte b) {
1324             return hash * 31 + b;
1325         }
1326 
1327         private static class End {
1328             int  centot;     // 4 bytes
1329             long cenlen;     // 4 bytes


1528         private static void zerror(String msg) throws ZipException {
1529             throw new ZipException(msg);
1530         }
1531 
1532         /*
1533          * Returns the {@code pos} of the zip cen entry corresponding to the
1534          * specified entry name, or -1 if not found.
1535          */
1536         private int getEntryPos(byte[] name, boolean addSlash) {
1537             if (total == 0) {
1538                 return -1;
1539             }
1540             int hsh = hashN(name, 0, name.length);
1541             int idx = table[(hsh & 0x7fffffff) % tablelen];
1542             /*
1543              * This while loop is an optimization where a double lookup
1544              * for name and name+/ is being performed. The name char
1545              * array has enough room at the end to try again with a
1546              * slash appended if the first table lookup does not succeed.
1547              */
1548             while (true) {
1549                 /*
1550                  * Search down the target hash chain for a entry whose
1551                  * 32 bit hash matches the hashed name.
1552                  */
1553                 while (idx != ZIP_ENDCHAIN) {
1554                     if (getEntryHash(idx) == hsh) {
1555                         // The CEN name must match the specfied one
1556                         int pos = getEntryPos(idx);
1557                         if (name.length == CENNAM(cen, pos)) {
1558                             boolean matched = true;
1559                             int nameoff = pos + CENHDR;
1560                             for (int i = 0; i < name.length; i++) {
1561                                 if (name[i] != cen[nameoff++]) {
1562                                     matched = false;
1563                                     break;
1564                                 }
1565                             }
1566                             if (matched) {
1567                                 return pos;
1568                             }


< prev index next >