Implement support for writing symlinks
Implement support for writing symlinks

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:

* There's no way to set FileOptions.permissions with the S_IFLNK bits
  set (FileOptions.unix_permissions() throws away bits beyond 0o777).
* Existing APIs for starting a "typed" (e.g. file or directory) entry
  automatically set the S_IFMT bits and could conflict with bits
  set on FileOptions.permissions.
* The low-level, generic start_entry() function isn't public.

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.

zip-rs/zip