zip-rs / zip-old

Zip implementation in Rust
MIT License
731 stars 204 forks source link

Implement support for writing symlinks #304

Closed indygreg closed 2 years ago

indygreg commented 2 years ago

The primary goal of this commit is to enable this library to emit zip archives with symlinks while minimizing the surface area of the change to hopefully enable the PR to merge with minimal controversy.

Today, it isn't possible to write symlinks with this library because there's no way to preserve the upper S_IFMT bits in the file mode bits because:

When implementing this, I initially added a FileOptions.unix_mode() function to allow setting all 16 bits in the eventual external attributes u32. However, I quickly realized this wouldn't be enough because APIs like start_file() do things like |= 0o100000. So if we went this route, we'd need to make consumers of FileOptions.permissions aware of when they should or shouldn't touch the high bits beyond 0o777.

I briefly thought about making FileOptions.permissions an enum with a variant to allow the st_mode bits to sail through unmodified. But this change seemed overly invasive, low level, and not very user-friendly.

So the approach I decided on was to define a new add_symlink() API. It follows the pattern of add_directory() and provides an easy-to-use and opionated API around the addition of a special file type.

I purposefully chose to not implement reading or extraction support for symlinks because a) I don't need the feature at the moment b) implementing symlink extraction in a way that works reliably on all platforms and doesn't have security issues is hard. I figured it was best to limit the scope of this change so this PR stands a good chance of being merged.

Partially implements #77.

zamazan4ik commented 2 years ago

Thanks for the PR! @Plecra I think we need your design review for this PR