Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compression.ZipArchive: Expose ExternalFileAttributes for Entries #20603

Closed
ianhays opened this issue Mar 13, 2017 · 12 comments · Fixed by dotnet/corefx#18565
Closed

Compression.ZipArchive: Expose ExternalFileAttributes for Entries #20603

ianhays opened this issue Mar 13, 2017 · 12 comments · Fixed by dotnet/corefx#18565
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.IO.Compression
Milestone

Comments

@ianhays
Copy link
Contributor

ianhays commented Mar 13, 2017

Problem

The ExternalFileAttributes field of a ZipArchiveEntry is currently hidden within the implementation and not accessible. This has been fine in the Windows world since it's not used but it is used by Unix's zip/unzip programs to store file permissions of an entry. As it currently stands, there is no way to carry Unix RWX permissions within a zip, so at unzip time the unzipper has to guess at permissions and manually chmod the entries.

https:/dotnet/corefx/issues/14853
https:/dotnet/corefx/issues/15516
https:/dotnet/corefx/issues/10223
NuGet/Home#4424

Solution

Permissions isn't an officially supported feature of the zip specification but it is used widely enough that we should add support for it. There's a pretty wide range of things we can do here that go from simply exposing the field all the way to implementing AccessControl for Unix and accepting something from there as input. Since the latter option requires a huge amount of work/new API and marries us to a Zip permissions structure, I suggest we take the simple/future-proof route here and just expose the entire field:

public partial class ZipArchiveEntry
{
    public int ExternalAttributes {get; set}
}

This also has the benefit of potentially supporting other implementations that use the external file attributes field for reasons other than permissions. I'm not aware of any of these off the top of my head, but they ostensibly exist.

Usage

The unfortunate aspect of exposing the raw field is that usage becomes a bit more complicated. However, without implementing our own UnixPermissions structure that's somewhat unavoidable. The nice thing is that it leaves us open to implement an explicit UnixPermissions structure in the future (pending the completion of #17540) without conflictions with the ExternalAttributes.

This StackOverflow post does a better job describing the format than I can so I'm just going to link it. The permissions values themselves are the same as the ones you get from stat.

cc: @stephentoub @JeremyKuhne

@ianhays ianhays self-assigned this Mar 13, 2017
@eerhardt
Copy link
Member

I like it. Thanks for writing this up.

I also like that making me happy is a benefit. 😆

@eerhardt
Copy link
Member

One quick question, the zip spec you pointed out just lists the "external file attributes" as "4 bytes". Would it make more sense to expose this as a uint?

@ianhays
Copy link
Contributor Author

ianhays commented Mar 14, 2017

Would it make more sense to expose this as a uint?

It would make more sense, yes. I get yelled at with CLS-Compliance errors when I switch it to uint though.

@eerhardt
Copy link
Member

I get yelled at with CLS-Compliance errors when I switch it to uint though.

😢

@stephentoub
Copy link
Member

I get yelled at with CLS-Compliance errors when I switch it to uint though

@terrajobst, how much do we care about CLS compliance around exposing uint from public surface area?

@ianhays
Copy link
Contributor Author

ianhays commented Mar 15, 2017

This is ready to go when @terrajobst decides on the int/uint API, so it'll be in for 2.0.0.

@terrajobst
Copy link
Member

We've just discussed this in great detail. There are multiple layers to this feature:

  1. Exposing the external attributes and round tripping it. We've no concerns and we believe this is a good idea.
  2. Recording permissions when zipping up on Unix. Seems useful, but we may want to make this opt-in or at least opt-out.
  3. Applying permission when extracting on Unix. Seems useful, but we may want to make this opt-in or at least opt-out.

The concern would be that (2) and (3) seems to complicate the API quit a bit. We're hesitant to just do it in all cases, because we can't easily change that later (without changing behavior). It seems the narrow is a bit too narrow to be worth adding new APIs. Thus, we should split this issue in (1) and (2)/(3). We'd just approve (1).

Questions:

  • Are there any other usages of external attributes that we may want to expose later? If so, we should design APIs with that in mind.
  • How do most zip/unzip libraries and tools on Unix/Linux deal with permissions?

@ianhays
Copy link
Contributor Author

ianhays commented Mar 21, 2017

We've no concerns and we believe this is a good idea.
Thus, we should split this issue in (1) and (2)/(3). We'd just approve (1).

Thanks for taking a look @terrajobst, I've split the ZipFile support to https:/dotnet/corefx/issues/17342 and edited the OP to only be for the ExternalAttribute exposure.

@eerhardt
Copy link
Member

@terrajobst - you didn't answer the questions:

Would it make more sense to expose this as a uint?
how much do we care about CLS compliance around exposing uint from public surface area?

@terrajobst
Copy link
Member

terrajobst commented Apr 18, 2017

Would it make more sense to expose this as a uint?

Good point, we discussed this and decided that uint is generally not worth the hassle. Especially for APIs that are essentially pass through for most devs. So we approved this API shape:

public partial class ZipArchiveEntry
{
    public int ExternalAttributes {get; set}
}

We still care about CLS compliance.

@danmoseley
Copy link
Member

Leaving in 2.0 for a couple more days since @ianhays says he has the change ready :)

@ianhays
Copy link
Contributor Author

ianhays commented Apr 18, 2017

Sure do! It'll be up today.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.0.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.IO.Compression
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants