Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZIP entries last modification time is rounded down on Java 8 or later #95

Closed
plamentotev opened this issue Aug 14, 2018 · 0 comments
Closed
Assignees
Labels
Milestone

Comments

@plamentotev
Copy link
Member

Short Description

According to the Plexus Archiver documentation:

    /**
     * Whether the file modification times will be rounded up to the
     * next even number of seconds.
     * <p/>
     * <p>
     * Zip archives store file modification times with a
     * granularity of two seconds, so the times will either be rounded
     * up or down. If you round down, the archive will always seem
     * out-of-date when you rerun the task, so the default is to round
     * up. Rounding up may lead to a different type of problems like
     * JSPs inside a web archive that seem to be slightly more recent
     * than precompiled pages, rendering precompilation useless.</p>
     *
     * <p/>
     * plexus-archiver chooses to round up.
     * <p/>
     * Java versions up to java7 round timestamp down, which means we add a heuristic value (which is slightly
     * questionable)
     * Java versions from 8 and up round timestamp up.
     * s
     */
    private static final boolean isJava7OrLower = getJavaVersion() <= 7;

but that is not true. A simple test shows that when run on Java 8 the entries last modified time is rounded down. If there are no objections I'll remove the check so the last modification times are rounded up (resulting in entries being with the same or newer last modification than the original file and not older) even on Java 8 and later.

Long Description

The ZIP file format stores the last modification time of an entry in DOS date time format - the date and time are stored in 16 bit integer value. This have some limitations but the important for the discussion is that 5 bits are used to store the seconds while to store value from 0 to 59 a 6 bits are required. Seconds are shifted by one bit (effectively dividing them by 2). In practice that means that odd seconds are stored with the same value as the lower even second. For example both 3 (0b11) and 2 (0b10) are stored as 1(0b1). What that means for Maven? Let's assume that a file last modification timestamp(in seconds) is 1534189011 then it will be stored as 1534189010 making the entry appear older than the original file.

What Have Changed in Java 8

Java 7 follows the description above. For example:

zipEntry.setTime(1534189011000L);
zipEntry.getTime(); // returns 1534189010000

effectively rounding the value down. In Java 8 on other hand:

zipEntry.setTime(1534189011000L);
zipEntry.getTime(); // returns 1534189011000

It does not do any rounding - it just returns the original value. That is because it internally stores if the value was rounded down so it can return the original value (you can check the source here).

Why it Does Not Matter

It does not matter if zipEntry.getTime() returns the original time or not because Commons Compress shifts the seconds value again before writing it to the ZIP file headers. From org.apache.commons.compress.archivers.zip,ZipUtil#toDosTime

        final long value =  ((year - 1980) << 25)
                |         (month << 21)
                |         (c.get(Calendar.DAY_OF_MONTH) << 16)
                |         (c.get(Calendar.HOUR_OF_DAY) << 11)
                |         (c.get(Calendar.MINUTE) << 5)
                |         (c.get(Calendar.SECOND) >> 1);
        ZipLong.putLong(value, buf, offset);
@plamentotev plamentotev added this to the 3.7.0 milestone Aug 14, 2018
@plamentotev plamentotev self-assigned this Aug 14, 2018
@plamentotev plamentotev changed the title ZIP entries file modification is rounded down on Java 8 or later ZIP entries last modification time is rounded down on Java 8 or later Aug 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant