mem/unix: overhaul ~completely (and fix some bugs)
mem/unix: overhaul ~completely (and fix some bugs)

UNSAFETY
========

Filesystems. Reference counting. Traversal.

My initial FileSystem implementation used Rc<RefCell<>> and had an
unsafe impl of Send/Sync. I changed that to Arc<RwLock<>> to remove the
unsafety.

This safety was a lie, though. It is absolutely unsafe to have to
filesystem functions occuring concurrently. What would happen if we were
to rename /a/b/c to /d/e/f, while simultaneously recursively removing
/a? The write lock for the recursive remove would block traversal,
leading to a deadlock.

After adding symlinks and everything else, I've grown paranoid that a
path could cycle back into itself holding a read lock. Additionally,
this entire time, I have been a bit peeved that every directory
traversal requires locks and clones.

Thus, enter unsafety. We have the public, outer facing filesystem: FS.
It is cloneable. It guards concurrent calls.

We have our internal filesystem, FileSystem. It has a custom Drop
implementation that actually cleans up raw pointers. We only ever have
one FileSystem and it is only ever dropped once every FS is dropped.

Lastly, we have our internal current directory. This is inside the
FileSystem. It contains raw pointers; we handle functions by traversing
from the current directory (or root if needed). Traversing drops
Raw<Dirent>'s, but dropping a Raw<> does not clean up its resources.

With these changes, we additionally have to clean up deleted Dirent's,
which can occur during remove_dir_all, remove_dir, and remove_file.

I've implemented a bunch of Deref's on structures to make access a lot
simpler. In the end, I believe the code is much cleaner, albeit,
occasionally, slightly harder to reason about safety wise.

INODES
======

It turns out, most of my metadata function calls were implemented
improperly. The real std::fs actually gets the most updated metadata
once called. I just saved the value once and then returned that for,
say, DirEntry.

Additionally, a File's set_permissions call did not need to traverse the
filesystem to set permissions. This is key because we can update open
file descriptors even if the underlying file has moved.

This changes a bunch of stuff all over to have metadata handled
properly, and it wraps this all up in a type called InodeData (which is
wrapped in Inode for concurrency). Permissions are now stored in
InodeData. As are file lengths.

This also preemptively adds access/modified/created times to InodeData.
I will be introducing a commit shortly that adds the final three missing
std::fs functions (metadata's time functions) to this module.

twmb/rsfs