Currently if we create archive on linux and set permissions and then extract all permissions are lost:
createArchive "2.zip" $ mkEntrySelector "checker" >>= \c -> loadEntry Store c "./tmp/problems/A/checker" >> setExternalFileAttrs 2179792896 c
The problem is that archive encodes MSDOS version, so unix permissions are ignored, result of unzip -Z1:
Central directory entry #1:
---------------------------
checker
offset of local header from start of archive: 0
(0000000000000000h) bytes
file system or operating system of origin: MS-DOS, OS/2 or NT FAT
version of encoding software: 4.6
minimum file system compatibility required: MS-DOS, OS/2 or NT FAT
minimum software version required to extract: 2.0
File created by the zip utility gives:
offset of local header from start of archive: 0
(0000000000000000h) bytes
file system or operating system of origin: Unix
version of encoding software: 3.0
minimum file system compatibility required: MS-DOS, OS/2 or NT FAT
Quoting spec:
4.4.2 version made by (2 bytes)
4.4.2.1 The upper byte indicates the compatibility of the file
attribute information. If the external file attributes
are compatible with MS-DOS and can be read by PKZIP for
DOS version 2.04g then this value will be zero. If these
attributes are not compatible, then this value will
identify the host system on which the attributes are
compatible. Software can use this information to determine
the line record format for text files etc.
4.4.2.2 The current mappings are:
0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
1 - Amiga 2 - OpenVMS
3 - UNIX 4 - VM/CMS
5 - Atari ST 6 - OS/2 H.P.F.S.
7 - Macintosh 8 - Z-System
9 - CP/M 10 - Windows NTFS
11 - MVS (OS/390 - Z/OS) 12 - VSE
13 - Acorn Risc 14 - VFAT
15 - alternate MVS 16 - BeOS
17 - Tandem 18 - OS/400
19 - OS X (Darwin) 20 thru 255 - unused
4.4.2.3 The lower byte indicates the ZIP specification version
(the version of this document) supported by the software
used to encode the file. The value/10 indicates the major
version number, and the value mod 10 is the minor version
number.
Currently toVersion always created MS-DOS or OS/2 version:
https://github.com/mrkkrp/zip/blob/master/Codec/Archive/Zip/Internal.hs#L976-L982
Changing the code to:
fromVersion :: Version -> Word16
fromVersion v = fromIntegral ((3 `shiftL` 8) .|. (major * 10 + minor))
where (major,minor) =
case versionBranch v of
v0:v1:_ -> (v0, v1)
v0:_ -> (v0, 0)
[] -> (0, 0)
As expected creates unix header, and permissions are not ignored by the unzip:
offset of local header from start of archive: 0
(0000000000000000h) bytes
file system or operating system of origin: Unix
version of encoding software: 4.6
minimum file system compatibility required: Unix
I'd like to have a fix here, but I'm not sure about the strategy, one way is to use CPP and pass current OS, then we can insert version base on the host OS. But I'm not sure it it will go against the package rules or not.
Currently if we create archive on linux and set permissions and then extract all permissions are lost:
The problem is that archive encodes MSDOS version, so unix permissions are ignored, result of
unzip -Z1:File created by the zip utility gives:
Quoting spec:
Currently toVersion always created
MS-DOS or OS/2version:https://github.com/mrkkrp/zip/blob/master/Codec/Archive/Zip/Internal.hs#L976-L982
Changing the code to:
As expected creates unix header, and permissions are not ignored by the unzip:
I'd like to have a fix here, but I'm not sure about the strategy, one way is to use CPP and pass current OS, then we can insert version base on the host OS. But I'm not sure it it will go against the package rules or not.