Cake: Zip doesn't preserve file permissions on Linux

Created on 5 Aug 2019  路  4Comments  路  Source: cake-build/cake

What You Are Seeing?

Using something like:

Zip(Directory("d"), File("test.zip"));

The zip file contents are correct, but linux file permissions (ugoa rwx) are not preserved within the zip file, when run on Linux.

What is Expected?

I should be able to list the zip file contents using unzip -Zl and see the linux file permissions that were set before zipping.

What version of Cake are you using?

dotnet core
cake.tool version '0.34.1'

Are you running on a 32 or 64 bit system?

64 bit

What environment are you running on? Windows? Linux? Mac?

Linux

Are you running on a CI Server? If so, which one?

Yes, but I see the same results running locally.

How Did You Get This To Happen? (Steps to Reproduce)

  1. Create a script file on Linux:
mkdir d
echo '#!/bin/bash' > d/test.sh 
echo "echo foo" >> d/test.sh 
chmod a+x d/test.sh
  1. Write a build.cake script to zip the directory:
    ```c#
    Zip(Directory("d"), File("test.zip"));
3. Install the cake.tool
```bash
dotnet tool install -g cake.tool
  1. Run the cake script
dotnet cake
  1. Check the contents of the zipped file:
$ unzip -Zl test.zip
Archive:  test.zip
Zip file size: 135 bytes, number of entries: 1
?---------  2.0 unx       21 b-       23 defN 19-Aug-05 14:13 test.sh
1 file, 21 bytes uncompressed, 23 bytes compressed:  -9.5%

In contrast, if the zip file is created with the linux zip command (infozip), the file contents are:

$ unzip -Zl linux-test.zip
Archive:  linux-test.zip
Zip file size: 185 bytes, number of entries: 1
-rwxrwxrwx  3.0 unx       21 tx       21 stor 19-Aug-05 14:13 test.sh
1 file, 21 bytes uncompressed, 21 bytes compressed:  0.0%

which shows that the file permissions are preserved in the zip file.

Help wanted Up-for-grabs

Most helpful comment

AFAIK as I know this is partially a limitation of .NET ZipEntry ( see dotnet/corefx#17342 )

There's work arounds i.e.

const int rw_rw_r = (0x8000 + 0x0100 + 0x0080 + 0x0020 + 0x0010 + 0x0004) << 16;
entry.ExternalAttributes = rw_rw_r;

would set read write / read write / read,

Code for zipping in cake is located here
https://github.com/cake-build/cake/blob/develop/src/Cake.Common/IO/Zipper.cs#L165-L192

Issue would be to in a clean way identify running on posix and identify correct file permissions for each file while guaranteeing to work with existing scripts.

All 4 comments

AFAIK as I know this is partially a limitation of .NET ZipEntry ( see dotnet/corefx#17342 )

There's work arounds i.e.

const int rw_rw_r = (0x8000 + 0x0100 + 0x0080 + 0x0020 + 0x0010 + 0x0004) << 16;
entry.ExternalAttributes = rw_rw_r;

would set read write / read write / read,

Code for zipping in cake is located here
https://github.com/cake-build/cake/blob/develop/src/Cake.Common/IO/Zipper.cs#L165-L192

Issue would be to in a clean way identify running on posix and identify correct file permissions for each file while guaranteeing to work with existing scripts.

Looks like you'd probably want to use the Mono.Posix.NETStandard NuGet package.

@gitfool yip probably, but unsure/need to evaluate if we want to take that dependency, probably a good use case to test in an addin first and promote to Cake itself once battle tested.

Link to the issue on the dotnet/runtime repo: Compression.ZipFile support for Unix Permissions.

Was this page helpful?
0 / 5 - 0 ratings