brimworks / lua-zip

Lua binding to libzip.
80 stars 25 forks source link

Tests fail: mtime #6

Closed MisterDA closed 8 years ago

MisterDA commented 8 years ago

Hi ! I am trying to reproduce the filesync option zip (in command-line) has, so I need to compare the last modification time a file has, from the related file in the zip archive. I encountered problem using the lib, and I ran the tests. It gave me this message :

# Expected [mtime] to be '1296450278', but got '1296417878'
not ok 12 - TEST.TXT stat
# Expected [mtime] to be '1296450278', but got '1296417878'
not ok 13 - index 2 stat
brimworks commented 8 years ago

Interesting that this is exactly 9 hour skew. This smells like timezone offset issues.... and based on this wiki page it probably is:

https://en.wikipedia.org/wiki/Zip_(file_format)#Structure

"The .ZIP format has no notion of time zone, so timestamps are only meaningful if it is known what time zone they were created in."

This appears to be a limitation of the ZIP format.

Sorry, -Brian

MisterDA commented 8 years ago

So there is no safe way to tell if a file in a zip archive is older than a file in the filesystem ? I was using this snippet, I added +100 as a workaround but I'm not sure if it is a good idea. What do you think ?

if lfs.attributes(file).modification > zip_arc:stat(index).mtime + 100 then
  -- filesystem is newer
end
brimworks commented 8 years ago

Depends on what you mean by "safe" :).

If you download the source to libzip and look at the lib/zip_dirent.c file you will see this is how the time embedded within the ZIP file is converted into epoch seconds:

static time_t
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
{
    struct tm tm;

    memset(&tm, 0, sizeof(tm));

    /* let mktime decide if DST is in effect */
    tm.tm_isdst = -1;

    tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
    tm.tm_mon = ((ddate>>5)&15) - 1;
    tm.tm_mday = ddate&31;

    tm.tm_hour = (dtime>>11)&31;
    tm.tm_min = (dtime>>5)&63;
    tm.tm_sec = (dtime<<1)&62;

    return mktime(&tm);
}

Two things to note:

Cheers, -Brian