Closed koron closed 8 years ago
素の zip にはタイムスタンプのロケールは記録されていない。
golangのarchive/zipはタイムスタンプをUTCとして取り扱う。
しかしzip自身はextended attributes (ZipFile#Extra
)としてロケールを持ってる場合がある。
archive/zipは ZipFile#Extra
を一部を除き、無視している。
以上の条件が重なって問題が発生している。
解決するには独自に ZipFile#Extra
からロケール情報を取り出す必要あり。
用語としてはextra field、拡張フィールドが正しいらしい。
4.5 Extensible data fields
--------------------------
4.5.1 In order to allow different programs and different types
of information to be stored in the 'extra' field in .ZIP
files, the following structure MUST be used for all
programs storing data in this field:
header1+data1 + header2+data2 . . .
Each header should consist of:
Header ID - 2 bytes
Data Size - 2 bytes
Note: all fields stored in Intel low-byte/high-byte order.
The Header ID field indicates the type of data that is in
the following data block.
Header IDs of 0 thru 31 are reserved for use by PKWARE.
The remaining IDs can be used by third party vendors for
proprietary usage.
4.5.2 The current Header ID mappings defined by PKWARE are:
0x0001 Zip64 extended information extra field
0x0007 AV Info
0x0008 Reserved for extended language encoding data (PFS)
(see APPENDIX D)
0x0009 OS/2
0x000a NTFS
0x000c OpenVMS
0x000d UNIX
0x000e Reserved for file stream and fork descriptors
0x000f Patch Descriptor
0x0014 PKCS#7 Store for X.509 Certificates
0x0015 X.509 Certificate ID and Signature for
individual file
0x0016 X.509 Certificate ID for Central Directory
0x0017 Strong Encryption Header
0x0018 Record Management Controls
0x0019 PKCS#7 Encryption Recipient Certificate List
0x0065 IBM S/390 (Z390), AS/400 (I400) attributes
- uncompressed
0x0066 Reserved for IBM S/390 (Z390), AS/400 (I400)
attributes - compressed
0x4690 POSZIP 4690 (reserved)
https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT より。
ロケールそのものではなさそう。
4.6.1 に 0x5455 extended timestamp
って書いてあるけど詳細には触れてない :cold_sweat:
golang の archive/zip は9時間ずれます
現状出来るのは filepath.Walk しながらタイムスタンプを戻すしかないです。
コードは流用してもらっていいです。
あざす! ちょっとどうするかは検討中
ざっくりみた感じ、そのコードでは解決できなさそう。
リリースしている zip は Info-ZIP で作ってるんですが、そのなかに NTFS や UNIX向けの拡張ヘッダがありませんでいた。 あったのはやはり 0x5455 、それと 0x7875 なのでこれを Extra から取り出して適用するコードが別途要りそう。
Gerrit にあった http://opensource.apple.com//source/zip/zip-6/unzip/unzip/proginfo/extra.fld これには 5455 解説されてた。しかし 7875 はない。 Info-Zip みちゃったほうが速いかな?
7875 https://issues.apache.org/jira/browse/COMPRESS-211
From Info Zip (zip-3.0)'s source archive (proginfo/extrafld.txt):
-Info-ZIP New Unix Extra Field:
====================================
Currently stores Unix UIDs/GIDs up to 32 bits.
(Last Revision 20080509)
Value Size Description
----- ---- -----------
(UnixN) 0x7875 Short tag for this extra block type ("ux")
TSize Short total data size for this block
Version 1 byte version of this extra field, currently 1
UIDSize 1 byte Size of UID field
UID Variable UID for this entry
GIDSize 1 byte Size of GID field
GID Variable GID for this entry
とりあえず Info-Zip の資料を抜き出しておいた。 https://github.com/koron/go-zipext/blob/master/doc/extrafld.txt go-zipext でちゃんとparseして、こちらで使う予定。
0x7875 って時刻情報ですか?UIDとGIDとサイズしかない様に見えます。
7875 は Info-ZIP がつけてる UNIX情報で、単に私の興味です。
いまフォーカスするべきは 5455 で 、手元ではこんな感じに別個パースしちゃいました。
$ ./lsext.exe ../netupvim/tmp/netupvim-v1.1.zip
netupvim.exe
ModTime: 2016-06-20 01:25:12 +0000 UTC
(EX)ModTime: 2016-06-20 01:25:12 +0900 JST
(EX)AcTime: 0001-01-01 00:00:00 +0000 UTC
(EX)CrTime: 0001-01-01 00:00:00 +0000 UTC
UPDATE.bat
ModTime: 2016-05-04 10:40:36 +0000 UTC
(EX)ModTime: 2016-05-04 10:40:36 +0900 JST
(EX)AcTime: 0001-01-01 00:00:00 +0000 UTC
(EX)CrTime: 0001-01-01 00:00:00 +0000 UTC
RESTORE.bat
ModTime: 2016-05-04 10:40:36 +0000 UTC
(EX)ModTime: 2016-05-04 10:40:36 +0900 JST
(EX)AcTime: 0001-01-01 00:00:00 +0000 UTC
(EX)CrTime: 0001-01-01 00:00:00 +0000 UTC
手元では動作確認済み。RESTORE.bat を叩くと日付が9時間巻き戻ったw
いかしまぁ早く僕の CL 取り込んで欲しい。。。
1.8 に先送りされてて絶望しましたわ。
とはいえUNIXでも良く使われる Info-Zip で作ったZIPファイルの時刻を抽出できないので、 現状のアレでは不足かもしれません。
7.4.1944-20160620 内の gvim.exe は 00:21 (JST) であるはずなのに、09:21 になってる。
つまり JST で記録されている 00:21 という値を、 UTC として扱って時刻に設定しているから 09:21 (JST) 扱いということか?