Skip to content

Archive version is set incorrectly. #62

@qnikst

Description

@qnikst

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting-prIssues that await a PR that would implement/solve thembug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions