On Mon, Mar 2, 2020 at 7:15 AM Volker Simonis <volker.simo...@gmail.com>
wrote:

> On Fri, Feb 28, 2020 at 8:02 PM Martin Buchholz <marti...@google.com>
> wrote:
> >
> > Welcome to the troublesome world of zip implementations!
> >
>
> Well, not many remember that the zip format was designed to work
> efficiently with floppy discs :)
>
> > It looks like by creating a new JarEntry you are discarding possible
> information from the old one, e.g. you might be discarding whether the
> input entry was compressed.  If "jar u" does that, I would consider it a
> bug!
> >
>
> You're right. My fix was a little to simple, and can be improved:
>
> http://cr.openjdk.java.net/~simonis/webrevs/2020/8240235.01
>
> Preserving the time, comment, extra information, compression method
> and size/CRC if the compression method was "stored" is the best we can
> do. And this is actually exactly what "jar -" does (see [1]).
>
> [1]
> http://hg.openjdk.java.net/jdk/jdk/file/e04746cec89c/src/jdk.jartool/share/classes/sun/tools/jar/Main.java#l934
>
>
This fix Looks Good To Me.


> > Arguably there is a missing API that would allow you to copy zip entries
> from an input to an output completely intact, without having to decompress
> and recompress.  (might be hard to design!)
> >
>
> Yes, I did think about this as well. It might not be that hard at all.
> We could simply add readRawEntry()/wrtiteRawEntry() methods to
> ZipInputStream/ZipOutputStream. We'd have to tweak
> ZipOutputStream.closeEntry() such that it can handle such "raw" writes
> (e.g. it wouldn't be able to check the CRC any more) and various
> methods like "skip()" in ZipInputStream. I think this might be
> interesting not only because it would allow updating zip-files without
> changing untouched entries, but also because it will considerably
> improve the speed of updating (i.e. we would save the time for
> repeatedly inflating and deflating). I'm not sure though how frequent
> the use-case of updating a zip-file really is?
>
> But that would definitely be a larger enhancement with SE scope. Do
> you think it's worth it?
>
>
The platform "should" have something like this, and I've had similar
thoughts myself in the past, and my employer would benefit, since there's a
lot of zip munging that happens when building large applications.  But as
always, we have trouble finding the time.


> > Probably there should be no such utility method as updateJarFile at
> all.  Perhaps instead the jar/zip code could be refactored so that tests
> can reuse the same code used by "jar u".
> >
>
> I'll leave that as an extra improvement for others :)
>
> > On Fri, Feb 28, 2020 at 10:50 AM Volker Simonis <
> volker.simo...@gmail.com> wrote:
> >>
> >> Hi,
> >>
> >> can I please have a review for this small test fix:
> >>
> >> http://cr.openjdk.java.net/~simonis/webrevs/2020/8240235/
> >> https://bugs.openjdk.java.net/browse/JDK-8240235
> >>
> >> JarUtils.updateJar() and JarUtils.updateJarFile() update jar files by
> >> reading JarEntry-s from a source jar file and writing these exact
> >> JarEntry-s to the destination jar file followed be the inflated and
> >> re-deflated data belonging to this entry.
> >>
> >> This approach is not correct, because JarEntry contains both, the
> >> compressed and uncompressed size of the corresponding entry. But the
> >> original Defalter which initially compressed that entry can be either
> >> different from the current one or it might have used a different
> >> compression level compared to the current Deflater which re-deflates
> >> the entry data.
> >>
> >> When the newly created entry is closed, the new compressed size will
> >> be checked against the original compressed size if that was recorded
> >> in the JarEntry and an exception will be thrown, when they differ:
> >>
> >> java.util.zip.ZipException: invalid entry compressed size (expected
> >> 237 but got 238 bytes)
> >>         at
> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
> >>         at
> java.base/java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:192)
> >>         at
> java.base/java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:108)
> >>         at jdk.test.lib.util.JarUtils.updateJar(JarUtils.java:294)
> >>         at jdk.test.lib.util.JarUtils.updateJar(JarUtils.java:252)
> >>         at HasUnsignedEntryTest.start(HasUnsignedEntryTest.java:77)
> >>         at HasUnsignedEntryTest.main(HasUnsignedEntryTest.java:44)
> >>         at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
> >> Method)
> >>         at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> >>         at
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> >>         at java.base/java.lang.reflect.Method.invoke(Method.java:564)
> >>         at
> com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
> >>         at java.base/java.lang.Thread.run(Thread.java:832)
> >>         Suppressed: java.util.zip.ZipException: invalid entry
> >> compressed size (expected 237 but got 238 bytes)
> >>                 at
> >>
> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
> >>                 at
> >> java.base/java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:360)
> >>                 at
> >>
> java.base/java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:237)
> >>                 at
> >> java.base/java.util.zip.ZipOutputStream.close(ZipOutputStream.java:377)
> >>                 at
> jdk.test.lib.util.JarUtils.updateJar(JarUtils.java:280)
> >>
> >> The fix is trivial. Instead of copying the JarEntry-s verbatim to the
> >> output stream, simply write newly created JarEntry-s to the output
> >> stream which only contain the entry name. This is also the way how
> >> this is handled by the jar tool, when it updates jar files.
> >>
> >> Thank you and best regards,
> >> Volker
>

Reply via email to