Remove everything except OWNERS

p9 is now part of the crosvm repository.

Test: m crosvm
Change-Id: I3c46b745bd3f216df8403385027699a94f3762a4
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 4fdfdbe..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2017 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Defines the Chromium OS style for automatic reformatting.
-# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
-# Please keep all directives after this one sorted alphabetically.
-BasedOnStyle: Chromium
-
-# This is permitted by the Google and Chromium style guides, and existing code
-# uses it heavily.
-AllowAllParametersOfDeclarationOnNextLine: true
-
-# NOLINT(reason) is used heavily by existing code.
-CommentPragmas: 'NOLINT:.*'
-
-# cpplint.py does smarter #include sorting than clang-format (the former ignores
-# case and changes '-' to '_').
-SortIncludes: false
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index de0d2e3..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# NOTE! Please use 'git ls-files -i --exclude-standard'
-# command after changing this file, to see if there are
-# any tracked files which get ignored after the change.
-#
-
-# Temp files (e.g. editors).
-*~
-*.sw[op]
-
-# Compiled objects.
-*.a
-*.o
-*.l[ao]
-*.so
-*.exe
-
-*.d
-*.depends
-.deps
-.libs
-
-*.gch
-*.gcda
-*.gcno
-
-# Common output files.
-*.dump
-*.out
-*.test
-
-# Protobuf files.
-*.pb.cc
-*.pb.h
-
-# Python files.
-*.pyc
-
-# Debug (e.g. gdb).
-.gdb_history
-.gdbinit
-
-core
-cscope.*
-tags
-tags_sorted_by_file
-
-# Patch files.
-*.diff
-*.orig
-*.rej
-
-# Nested git repos.
-/glbench/images/
-
-# Cargo lock file.
-Cargo.lock
-
-# Cargo build directories.
-target/
-
-# VSCode source dirs
-.vscode/
-
-# Intellij project dirs
-.idea
-
-# clangd cache dir
-.clangd
-.cache
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index fe386a1..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,82 +0,0 @@
-// This file is generated by cargo2android.py --run --device --tests --dependencies --global_defaults=crosvm_defaults.
-
-package {
-    default_applicable_licenses: ["external_vm_tools_p9_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
-    name: "external_vm_tools_p9_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-BSD",
-    ],
-    license_text: [
-        "LICENSE",
-    ],
-}
-
-rust_library {
-    name: "libp9",
-    defaults: ["crosvm_defaults"],
-    host_supported: true,
-    crate_name: "p9",
-    srcs: ["src/lib.rs"],
-    edition: "2018",
-    rustlibs: [
-        "liblibc",
-        "liblibchromeos",
-    ],
-    proc_macros: ["libwire_format_derive"],
-}
-
-rust_defaults {
-    name: "p9_defaults",
-    defaults: ["crosvm_defaults"],
-    crate_name: "p9",
-    srcs: ["src/lib.rs"],
-    test_suites: ["general-tests"],
-    auto_gen_config: true,
-    edition: "2018",
-    rustlibs: [
-        "liblibc",
-        "liblibchromeos",
-    ],
-    proc_macros: ["libwire_format_derive"],
-}
-
-rust_test_host {
-    name: "p9_host_test_src_lib",
-    defaults: ["p9_defaults"],
-}
-
-rust_test {
-    name: "p9_device_test_src_lib",
-    defaults: ["p9_defaults"],
-}
-
-// dependent_library ["feature_list"]
-//   ../../crosvm/assertions/src/lib.rs
-//   ../../crosvm/data_model/src/lib.rs
-//   ../../libchromeos-rs/src/lib.rs
-//   autocfg-1.0.1
-//   cfg-if-0.1.10
-//   futures-0.3.9 "alloc"
-//   futures-channel-0.3.9 "alloc,futures-sink,sink"
-//   futures-core-0.3.9 "alloc"
-//   futures-io-0.3.9
-//   futures-sink-0.3.9 "alloc"
-//   futures-task-0.3.9 "alloc"
-//   futures-util-0.3.9 "alloc,futures-sink,sink"
-//   intrusive-collections-0.9.0 "alloc,default"
-//   libc-0.2.82 "default,std"
-//   log-0.4.11
-//   memoffset-0.5.6 "default"
-//   pin-project-lite-0.2.1
-//   pin-utils-0.1.0
-//   proc-macro2-1.0.24 "default,proc-macro"
-//   protobuf-2.20.0
-//   quote-1.0.8 "default,proc-macro"
-//   syn-1.0.58 "clone-impls,default,derive,parsing,printing,proc-macro,quote"
-//   unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
deleted file mode 100644
index 11ea913..0000000
--- a/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "p9"
-version = "0.1.0"
-authors = ["The Chromium OS Authors"]
-edition = "2018"
-
-[dependencies]
-libc = "*"
-libchromeos = { path = "../../libchromeos-rs" } # provided by ebuild
-wire_format_derive = { path = "wire_format_derive", version = "*" }
-
-[features]
-trace = []
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index b9e779f..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/METADATA b/METADATA
deleted file mode 100644
index 4626851..0000000
--- a/METADATA
+++ /dev/null
@@ -1,14 +0,0 @@
-name: "p9"
-description:
-    "Server implementation of the [9p] file system protocol. Taken from "
-    "chromium/platform2, vm_tools/p9."
-
-third_party {
-  url {
-    type: GIT
-    value: "https://chromium.googlesource.com/chromiumos/platform2"
-  }
-  version: "2c3e8252c684673e83278a0124a998e997dbbcc2"
-  last_upgrade_date { year: 2020 month: 12 day: 3 }
-  license_type: NOTICE
-}
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_BSD
+++ /dev/null
diff --git a/README.md b/README.md
deleted file mode 100644
index b85cc15..0000000
--- a/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# p9 - Server implementation of the [9p] file system protocol
-
-This directory contains the protocol definition and a server implementation of
-the [9p] file system protocol.
-
-*   [wire_format_derive] - A [procedural macro] that derives the serialization
-    and de-serialization implementation for a struct into the [9p] wire
-    format.
-*   [src/protocol] - Defines all the messages used in the [9p] protocol.  Also
-    implements serialization and de-serialization for some base types
-    (integers, strings, vectors) that form the foundation of all [9p]
-    messages.  Wire format implementations for all other messages are derived
-    using the `wire_format_derive` macro.
-*   [src/server.rs] - Implements a full [9p] server, carrying out file system
-    requests on behalf of clients.
-
-[9p]: http://man.cat-v.org/plan_9/5/intro
-[procedural macro]: https://doc.rust-lang.org/proc_macro/index.html
-[src/protocol]: src/protocol/
-[src/server.rs]: src/server.rs
-[wire_format_derive]: wire_format_derive/
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
deleted file mode 100644
index 1220681..0000000
--- a/fuzz/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "p9-fuzz"
-version = "0.1.0"
-authors = ["The Chromium OS Authors"]
-edition = "2018"
-
-[dependencies]
-p9 = { path = "../" }
-cros_fuzz = "*"
-
-[workspace]
-members = ["."]
-
-[[bin]]
-name = "p9_tframe_decode_fuzzer"
-path = "tframe_decode.rs"
-
-[patch.crates-io]
-wire_format_derive = { path = "../wire_format_derive" }
\ No newline at end of file
diff --git a/fuzz/OWNERS b/fuzz/OWNERS
deleted file mode 100644
index cef66ae..0000000
--- a/fuzz/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# ANDROID: Remove because Gerrit does not recognize these emails and reject the upload.
-#chirantan@chromium.org
-#dgreid@chromium.org
\ No newline at end of file
diff --git a/fuzz/tframe_decode.rs b/fuzz/tframe_decode.rs
deleted file mode 100644
index 6cdeae3..0000000
--- a/fuzz/tframe_decode.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#![no_main]
-
-use cros_fuzz::fuzz_target;
-use p9::fuzzing::tframe_decode;
-
-fuzz_target!(|bytes: &[u8]| {
-    tframe_decode(bytes);
-});
diff --git a/src/fuzzing.rs b/src/fuzzing.rs
deleted file mode 100644
index 0ba8e23..0000000
--- a/src/fuzzing.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use std::io::Cursor;
-
-use crate::protocol::{Tframe, WireFormat};
-
-pub fn tframe_decode(bytes: &[u8]) {
-    let mut cursor = Cursor::new(bytes);
-
-    while let Ok(_) = Tframe::decode(&mut cursor) {}
-}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index b00c706..0000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-extern crate libc;
-
-#[macro_use]
-extern crate wire_format_derive;
-
-mod protocol;
-mod server;
-
-#[cfg(fuzzing)]
-pub mod fuzzing;
-
-pub use server::*;
diff --git a/src/protocol/messages.rs b/src/protocol/messages.rs
deleted file mode 100644
index b5a03c0..0000000
--- a/src/protocol/messages.rs
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use std::io::{self, ErrorKind, Read, Write};
-use std::mem;
-use std::string::String;
-use std::vec::Vec;
-
-use crate::protocol::wire_format::{Data, WireFormat};
-
-// Message type constants.  Taken from "include/net/9p/9p.h" in the linux kernel
-// tree.  The protocol specifies each R* message to be the corresponding T*
-// message plus one.
-const TLERROR: u8 = 6;
-const RLERROR: u8 = TLERROR + 1;
-const TSTATFS: u8 = 8;
-const RSTATFS: u8 = TSTATFS + 1;
-const TLOPEN: u8 = 12;
-const RLOPEN: u8 = TLOPEN + 1;
-const TLCREATE: u8 = 14;
-const RLCREATE: u8 = TLCREATE + 1;
-const TSYMLINK: u8 = 16;
-const RSYMLINK: u8 = TSYMLINK + 1;
-const TMKNOD: u8 = 18;
-const RMKNOD: u8 = TMKNOD + 1;
-const TRENAME: u8 = 20;
-const RRENAME: u8 = TRENAME + 1;
-const TREADLINK: u8 = 22;
-const RREADLINK: u8 = TREADLINK + 1;
-const TGETATTR: u8 = 24;
-const RGETATTR: u8 = TGETATTR + 1;
-const TSETATTR: u8 = 26;
-const RSETATTR: u8 = TSETATTR + 1;
-const TXATTRWALK: u8 = 30;
-const RXATTRWALK: u8 = TXATTRWALK + 1;
-const TXATTRCREATE: u8 = 32;
-const RXATTRCREATE: u8 = TXATTRCREATE + 1;
-const TREADDIR: u8 = 40;
-const RREADDIR: u8 = TREADDIR + 1;
-const TFSYNC: u8 = 50;
-const RFSYNC: u8 = TFSYNC + 1;
-const TLOCK: u8 = 52;
-const RLOCK: u8 = TLOCK + 1;
-const TGETLOCK: u8 = 54;
-const RGETLOCK: u8 = TGETLOCK + 1;
-const TLINK: u8 = 70;
-const RLINK: u8 = TLINK + 1;
-const TMKDIR: u8 = 72;
-const RMKDIR: u8 = TMKDIR + 1;
-const TRENAMEAT: u8 = 74;
-const RRENAMEAT: u8 = TRENAMEAT + 1;
-const TUNLINKAT: u8 = 76;
-const RUNLINKAT: u8 = TUNLINKAT + 1;
-const TVERSION: u8 = 100;
-const RVERSION: u8 = TVERSION + 1;
-const TAUTH: u8 = 102;
-const RAUTH: u8 = TAUTH + 1;
-const TATTACH: u8 = 104;
-const RATTACH: u8 = TATTACH + 1;
-const _TERROR: u8 = 106;
-const _RERROR: u8 = _TERROR + 1;
-const TFLUSH: u8 = 108;
-const RFLUSH: u8 = TFLUSH + 1;
-const TWALK: u8 = 110;
-const RWALK: u8 = TWALK + 1;
-const _TOPEN: u8 = 112;
-const _ROPEN: u8 = _TOPEN + 1;
-const _TCREATE: u8 = 114;
-const _RCREATE: u8 = _TCREATE + 1;
-const TREAD: u8 = 116;
-const RREAD: u8 = TREAD + 1;
-const TWRITE: u8 = 118;
-const RWRITE: u8 = TWRITE + 1;
-const TCLUNK: u8 = 120;
-const RCLUNK: u8 = TCLUNK + 1;
-const TREMOVE: u8 = 122;
-const RREMOVE: u8 = TREMOVE + 1;
-const _TSTAT: u8 = 124;
-const _RSTAT: u8 = _TSTAT + 1;
-const _TWSTAT: u8 = 126;
-const _RWSTAT: u8 = _TWSTAT + 1;
-
-/// A message sent from a 9P client to a 9P server.
-#[derive(Debug)]
-pub enum Tmessage {
-    Version(Tversion),
-    Flush(Tflush),
-    Walk(Twalk),
-    Read(Tread),
-    Write(Twrite),
-    Clunk(Tclunk),
-    Remove(Tremove),
-    Attach(Tattach),
-    Auth(Tauth),
-    Statfs(Tstatfs),
-    Lopen(Tlopen),
-    Lcreate(Tlcreate),
-    Symlink(Tsymlink),
-    Mknod(Tmknod),
-    Rename(Trename),
-    Readlink(Treadlink),
-    GetAttr(Tgetattr),
-    SetAttr(Tsetattr),
-    XattrWalk(Txattrwalk),
-    XattrCreate(Txattrcreate),
-    Readdir(Treaddir),
-    Fsync(Tfsync),
-    Lock(Tlock),
-    GetLock(Tgetlock),
-    Link(Tlink),
-    Mkdir(Tmkdir),
-    RenameAt(Trenameat),
-    UnlinkAt(Tunlinkat),
-}
-
-#[derive(Debug)]
-pub struct Tframe {
-    pub tag: u16,
-    pub msg: Tmessage,
-}
-
-impl WireFormat for Tframe {
-    fn byte_size(&self) -> u32 {
-        let msg_size = match self.msg {
-            Tmessage::Version(ref version) => version.byte_size(),
-            Tmessage::Flush(ref flush) => flush.byte_size(),
-            Tmessage::Walk(ref walk) => walk.byte_size(),
-            Tmessage::Read(ref read) => read.byte_size(),
-            Tmessage::Write(ref write) => write.byte_size(),
-            Tmessage::Clunk(ref clunk) => clunk.byte_size(),
-            Tmessage::Remove(ref remove) => remove.byte_size(),
-            Tmessage::Attach(ref attach) => attach.byte_size(),
-            Tmessage::Auth(ref auth) => auth.byte_size(),
-            Tmessage::Statfs(ref statfs) => statfs.byte_size(),
-            Tmessage::Lopen(ref lopen) => lopen.byte_size(),
-            Tmessage::Lcreate(ref lcreate) => lcreate.byte_size(),
-            Tmessage::Symlink(ref symlink) => symlink.byte_size(),
-            Tmessage::Mknod(ref mknod) => mknod.byte_size(),
-            Tmessage::Rename(ref rename) => rename.byte_size(),
-            Tmessage::Readlink(ref readlink) => readlink.byte_size(),
-            Tmessage::GetAttr(ref getattr) => getattr.byte_size(),
-            Tmessage::SetAttr(ref setattr) => setattr.byte_size(),
-            Tmessage::XattrWalk(ref xattrwalk) => xattrwalk.byte_size(),
-            Tmessage::XattrCreate(ref xattrcreate) => xattrcreate.byte_size(),
-            Tmessage::Readdir(ref readdir) => readdir.byte_size(),
-            Tmessage::Fsync(ref fsync) => fsync.byte_size(),
-            Tmessage::Lock(ref lock) => lock.byte_size(),
-            Tmessage::GetLock(ref getlock) => getlock.byte_size(),
-            Tmessage::Link(ref link) => link.byte_size(),
-            Tmessage::Mkdir(ref mkdir) => mkdir.byte_size(),
-            Tmessage::RenameAt(ref renameat) => renameat.byte_size(),
-            Tmessage::UnlinkAt(ref unlinkat) => unlinkat.byte_size(),
-        };
-
-        // size + type + tag + message size
-        (mem::size_of::<u32>() + mem::size_of::<u8>() + mem::size_of::<u16>()) as u32 + msg_size
-    }
-
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-        self.byte_size().encode(writer)?;
-
-        let ty = match self.msg {
-            Tmessage::Version(_) => TVERSION,
-            Tmessage::Flush(_) => TFLUSH,
-            Tmessage::Walk(_) => TWALK,
-            Tmessage::Read(_) => TREAD,
-            Tmessage::Write(_) => TWRITE,
-            Tmessage::Clunk(_) => TCLUNK,
-            Tmessage::Remove(_) => TREMOVE,
-            Tmessage::Attach(_) => TATTACH,
-            Tmessage::Auth(_) => TAUTH,
-            Tmessage::Statfs(_) => TSTATFS,
-            Tmessage::Lopen(_) => TLOPEN,
-            Tmessage::Lcreate(_) => TLCREATE,
-            Tmessage::Symlink(_) => TSYMLINK,
-            Tmessage::Mknod(_) => TMKNOD,
-            Tmessage::Rename(_) => TRENAME,
-            Tmessage::Readlink(_) => TREADLINK,
-            Tmessage::GetAttr(_) => TGETATTR,
-            Tmessage::SetAttr(_) => TSETATTR,
-            Tmessage::XattrWalk(_) => TXATTRWALK,
-            Tmessage::XattrCreate(_) => TXATTRCREATE,
-            Tmessage::Readdir(_) => TREADDIR,
-            Tmessage::Fsync(_) => TFSYNC,
-            Tmessage::Lock(_) => TLOCK,
-            Tmessage::GetLock(_) => TGETLOCK,
-            Tmessage::Link(_) => TLINK,
-            Tmessage::Mkdir(_) => TMKDIR,
-            Tmessage::RenameAt(_) => TRENAMEAT,
-            Tmessage::UnlinkAt(_) => TUNLINKAT,
-        };
-
-        ty.encode(writer)?;
-        self.tag.encode(writer)?;
-
-        match self.msg {
-            Tmessage::Version(ref version) => version.encode(writer),
-            Tmessage::Flush(ref flush) => flush.encode(writer),
-            Tmessage::Walk(ref walk) => walk.encode(writer),
-            Tmessage::Read(ref read) => read.encode(writer),
-            Tmessage::Write(ref write) => write.encode(writer),
-            Tmessage::Clunk(ref clunk) => clunk.encode(writer),
-            Tmessage::Remove(ref remove) => remove.encode(writer),
-            Tmessage::Attach(ref attach) => attach.encode(writer),
-            Tmessage::Auth(ref auth) => auth.encode(writer),
-            Tmessage::Statfs(ref statfs) => statfs.encode(writer),
-            Tmessage::Lopen(ref lopen) => lopen.encode(writer),
-            Tmessage::Lcreate(ref lcreate) => lcreate.encode(writer),
-            Tmessage::Symlink(ref symlink) => symlink.encode(writer),
-            Tmessage::Mknod(ref mknod) => mknod.encode(writer),
-            Tmessage::Rename(ref rename) => rename.encode(writer),
-            Tmessage::Readlink(ref readlink) => readlink.encode(writer),
-            Tmessage::GetAttr(ref getattr) => getattr.encode(writer),
-            Tmessage::SetAttr(ref setattr) => setattr.encode(writer),
-            Tmessage::XattrWalk(ref xattrwalk) => xattrwalk.encode(writer),
-            Tmessage::XattrCreate(ref xattrcreate) => xattrcreate.encode(writer),
-            Tmessage::Readdir(ref readdir) => readdir.encode(writer),
-            Tmessage::Fsync(ref fsync) => fsync.encode(writer),
-            Tmessage::Lock(ref lock) => lock.encode(writer),
-            Tmessage::GetLock(ref getlock) => getlock.encode(writer),
-            Tmessage::Link(ref link) => link.encode(writer),
-            Tmessage::Mkdir(ref mkdir) => mkdir.encode(writer),
-            Tmessage::RenameAt(ref renameat) => renameat.encode(writer),
-            Tmessage::UnlinkAt(ref unlinkat) => unlinkat.encode(writer),
-        }
-    }
-
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-        let byte_size: u32 = WireFormat::decode(reader)?;
-
-        // byte_size includes the size of byte_size so remove that from the
-        // expected length of the message.  Also make sure that byte_size is at least
-        // that long to begin with.
-        if byte_size < mem::size_of::<u32>() as u32 {
-            return Err(io::Error::new(
-                ErrorKind::InvalidData,
-                format!("byte_size(= {}) is less than 4 bytes", byte_size),
-            ));
-        }
-
-        let reader = &mut reader.take((byte_size - mem::size_of::<u32>() as u32) as u64);
-
-        let mut ty = [0u8];
-        reader.read_exact(&mut ty)?;
-
-        let tag: u16 = WireFormat::decode(reader)?;
-
-        let msg = match ty[0] {
-            TVERSION => Ok(Tmessage::Version(WireFormat::decode(reader)?)),
-            TFLUSH => Ok(Tmessage::Flush(WireFormat::decode(reader)?)),
-            TWALK => Ok(Tmessage::Walk(WireFormat::decode(reader)?)),
-            TREAD => Ok(Tmessage::Read(WireFormat::decode(reader)?)),
-            TWRITE => Ok(Tmessage::Write(WireFormat::decode(reader)?)),
-            TCLUNK => Ok(Tmessage::Clunk(WireFormat::decode(reader)?)),
-            TREMOVE => Ok(Tmessage::Remove(WireFormat::decode(reader)?)),
-            TATTACH => Ok(Tmessage::Attach(WireFormat::decode(reader)?)),
-            TAUTH => Ok(Tmessage::Auth(WireFormat::decode(reader)?)),
-            TSTATFS => Ok(Tmessage::Statfs(WireFormat::decode(reader)?)),
-            TLOPEN => Ok(Tmessage::Lopen(WireFormat::decode(reader)?)),
-            TLCREATE => Ok(Tmessage::Lcreate(WireFormat::decode(reader)?)),
-            TSYMLINK => Ok(Tmessage::Symlink(WireFormat::decode(reader)?)),
-            TMKNOD => Ok(Tmessage::Mknod(WireFormat::decode(reader)?)),
-            TRENAME => Ok(Tmessage::Rename(WireFormat::decode(reader)?)),
-            TREADLINK => Ok(Tmessage::Readlink(WireFormat::decode(reader)?)),
-            TGETATTR => Ok(Tmessage::GetAttr(WireFormat::decode(reader)?)),
-            TSETATTR => Ok(Tmessage::SetAttr(WireFormat::decode(reader)?)),
-            TXATTRWALK => Ok(Tmessage::XattrWalk(WireFormat::decode(reader)?)),
-            TXATTRCREATE => Ok(Tmessage::XattrCreate(WireFormat::decode(reader)?)),
-            TREADDIR => Ok(Tmessage::Readdir(WireFormat::decode(reader)?)),
-            TFSYNC => Ok(Tmessage::Fsync(WireFormat::decode(reader)?)),
-            TLOCK => Ok(Tmessage::Lock(WireFormat::decode(reader)?)),
-            TGETLOCK => Ok(Tmessage::GetLock(WireFormat::decode(reader)?)),
-            TLINK => Ok(Tmessage::Link(WireFormat::decode(reader)?)),
-            TMKDIR => Ok(Tmessage::Mkdir(WireFormat::decode(reader)?)),
-            TRENAMEAT => Ok(Tmessage::RenameAt(WireFormat::decode(reader)?)),
-            TUNLINKAT => Ok(Tmessage::UnlinkAt(WireFormat::decode(reader)?)),
-            err => Err(io::Error::new(
-                ErrorKind::InvalidData,
-                format!("unknown message type {}", err),
-            )),
-        }?;
-
-        Ok(Tframe { tag, msg })
-    }
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tversion {
-    pub msize: u32,
-    pub version: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tflush {
-    pub oldtag: u16,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Twalk {
-    pub fid: u32,
-    pub newfid: u32,
-    pub wnames: Vec<String>,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tread {
-    pub fid: u32,
-    pub offset: u64,
-    pub count: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Twrite {
-    pub fid: u32,
-    pub offset: u64,
-    pub data: Data,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tclunk {
-    pub fid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tremove {
-    pub fid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tauth {
-    pub afid: u32,
-    pub uname: String,
-    pub aname: String,
-    pub n_uname: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tattach {
-    pub fid: u32,
-    pub afid: u32,
-    pub uname: String,
-    pub aname: String,
-    pub n_uname: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tstatfs {
-    pub fid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tlopen {
-    pub fid: u32,
-    pub flags: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tlcreate {
-    pub fid: u32,
-    pub name: String,
-    pub flags: u32,
-    pub mode: u32,
-    pub gid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tsymlink {
-    pub fid: u32,
-    pub name: String,
-    pub symtgt: String,
-    pub gid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tmknod {
-    pub dfid: u32,
-    pub name: String,
-    pub mode: u32,
-    pub major: u32,
-    pub minor: u32,
-    pub gid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Trename {
-    pub fid: u32,
-    pub dfid: u32,
-    pub name: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Treadlink {
-    pub fid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tgetattr {
-    pub fid: u32,
-    pub request_mask: u64,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tsetattr {
-    pub fid: u32,
-    pub valid: u32,
-    pub mode: u32,
-    pub uid: u32,
-    pub gid: u32,
-    pub size: u64,
-    pub atime_sec: u64,
-    pub atime_nsec: u64,
-    pub mtime_sec: u64,
-    pub mtime_nsec: u64,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Txattrwalk {
-    pub fid: u32,
-    pub newfid: u32,
-    pub name: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Txattrcreate {
-    pub fid: u32,
-    pub name: String,
-    pub attr_size: u64,
-    pub flags: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Treaddir {
-    pub fid: u32,
-    pub offset: u64,
-    pub count: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tfsync {
-    pub fid: u32,
-    pub datasync: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tlock {
-    pub fid: u32,
-    pub type_: u8,
-    pub flags: u32,
-    pub start: u64,
-    pub length: u64,
-    pub proc_id: u32,
-    pub client_id: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tgetlock {
-    pub fid: u32,
-    pub type_: u8,
-    pub start: u64,
-    pub length: u64,
-    pub proc_id: u32,
-    pub client_id: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tlink {
-    pub dfid: u32,
-    pub fid: u32,
-    pub name: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tmkdir {
-    pub dfid: u32,
-    pub name: String,
-    pub mode: u32,
-    pub gid: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Trenameat {
-    pub olddirfid: u32,
-    pub oldname: String,
-    pub newdirfid: u32,
-    pub newname: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Tunlinkat {
-    pub dirfd: u32,
-    pub name: String,
-    pub flags: u32,
-}
-
-/// A message sent from a 9P server to a 9P client in response to a request from
-/// that client.  Encapsulates a full frame.
-#[derive(Debug)]
-pub enum Rmessage {
-    Version(Rversion),
-    Flush,
-    Walk(Rwalk),
-    Read(Rread),
-    Write(Rwrite),
-    Clunk,
-    Remove,
-    Attach(Rattach),
-    Auth(Rauth),
-    Statfs(Rstatfs),
-    Lopen(Rlopen),
-    Lcreate(Rlcreate),
-    Symlink(Rsymlink),
-    Mknod(Rmknod),
-    Rename,
-    Readlink(Rreadlink),
-    GetAttr(Rgetattr),
-    SetAttr,
-    XattrWalk(Rxattrwalk),
-    XattrCreate,
-    Readdir(Rreaddir),
-    Fsync,
-    Lock(Rlock),
-    GetLock(Rgetlock),
-    Link,
-    Mkdir(Rmkdir),
-    RenameAt,
-    UnlinkAt,
-    Lerror(Rlerror),
-}
-
-#[derive(Debug)]
-pub struct Rframe {
-    pub tag: u16,
-    pub msg: Rmessage,
-}
-
-impl WireFormat for Rframe {
-    fn byte_size(&self) -> u32 {
-        let msg_size = match self.msg {
-            Rmessage::Version(ref version) => version.byte_size(),
-            Rmessage::Flush => 0,
-            Rmessage::Walk(ref walk) => walk.byte_size(),
-            Rmessage::Read(ref read) => read.byte_size(),
-            Rmessage::Write(ref write) => write.byte_size(),
-            Rmessage::Clunk => 0,
-            Rmessage::Remove => 0,
-            Rmessage::Attach(ref attach) => attach.byte_size(),
-            Rmessage::Auth(ref auth) => auth.byte_size(),
-            Rmessage::Statfs(ref statfs) => statfs.byte_size(),
-            Rmessage::Lopen(ref lopen) => lopen.byte_size(),
-            Rmessage::Lcreate(ref lcreate) => lcreate.byte_size(),
-            Rmessage::Symlink(ref symlink) => symlink.byte_size(),
-            Rmessage::Mknod(ref mknod) => mknod.byte_size(),
-            Rmessage::Rename => 0,
-            Rmessage::Readlink(ref readlink) => readlink.byte_size(),
-            Rmessage::GetAttr(ref getattr) => getattr.byte_size(),
-            Rmessage::SetAttr => 0,
-            Rmessage::XattrWalk(ref xattrwalk) => xattrwalk.byte_size(),
-            Rmessage::XattrCreate => 0,
-            Rmessage::Readdir(ref readdir) => readdir.byte_size(),
-            Rmessage::Fsync => 0,
-            Rmessage::Lock(ref lock) => lock.byte_size(),
-            Rmessage::GetLock(ref getlock) => getlock.byte_size(),
-            Rmessage::Link => 0,
-            Rmessage::Mkdir(ref mkdir) => mkdir.byte_size(),
-            Rmessage::RenameAt => 0,
-            Rmessage::UnlinkAt => 0,
-            Rmessage::Lerror(ref lerror) => lerror.byte_size(),
-        };
-
-        // size + type + tag + message size
-        (mem::size_of::<u32>() + mem::size_of::<u8>() + mem::size_of::<u16>()) as u32 + msg_size
-    }
-
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-        self.byte_size().encode(writer)?;
-
-        let ty = match self.msg {
-            Rmessage::Version(_) => RVERSION,
-            Rmessage::Flush => RFLUSH,
-            Rmessage::Walk(_) => RWALK,
-            Rmessage::Read(_) => RREAD,
-            Rmessage::Write(_) => RWRITE,
-            Rmessage::Clunk => RCLUNK,
-            Rmessage::Remove => RREMOVE,
-            Rmessage::Attach(_) => RATTACH,
-            Rmessage::Auth(_) => RAUTH,
-            Rmessage::Statfs(_) => RSTATFS,
-            Rmessage::Lopen(_) => RLOPEN,
-            Rmessage::Lcreate(_) => RLCREATE,
-            Rmessage::Symlink(_) => RSYMLINK,
-            Rmessage::Mknod(_) => RMKNOD,
-            Rmessage::Rename => RRENAME,
-            Rmessage::Readlink(_) => RREADLINK,
-            Rmessage::GetAttr(_) => RGETATTR,
-            Rmessage::SetAttr => RSETATTR,
-            Rmessage::XattrWalk(_) => RXATTRWALK,
-            Rmessage::XattrCreate => RXATTRCREATE,
-            Rmessage::Readdir(_) => RREADDIR,
-            Rmessage::Fsync => RFSYNC,
-            Rmessage::Lock(_) => RLOCK,
-            Rmessage::GetLock(_) => RGETLOCK,
-            Rmessage::Link => RLINK,
-            Rmessage::Mkdir(_) => RMKDIR,
-            Rmessage::RenameAt => RRENAMEAT,
-            Rmessage::UnlinkAt => RUNLINKAT,
-            Rmessage::Lerror(_) => RLERROR,
-        };
-
-        ty.encode(writer)?;
-        self.tag.encode(writer)?;
-
-        match self.msg {
-            Rmessage::Version(ref version) => version.encode(writer),
-            Rmessage::Flush => Ok(()),
-            Rmessage::Walk(ref walk) => walk.encode(writer),
-            Rmessage::Read(ref read) => read.encode(writer),
-            Rmessage::Write(ref write) => write.encode(writer),
-            Rmessage::Clunk => Ok(()),
-            Rmessage::Remove => Ok(()),
-            Rmessage::Attach(ref attach) => attach.encode(writer),
-            Rmessage::Auth(ref auth) => auth.encode(writer),
-            Rmessage::Statfs(ref statfs) => statfs.encode(writer),
-            Rmessage::Lopen(ref lopen) => lopen.encode(writer),
-            Rmessage::Lcreate(ref lcreate) => lcreate.encode(writer),
-            Rmessage::Symlink(ref symlink) => symlink.encode(writer),
-            Rmessage::Mknod(ref mknod) => mknod.encode(writer),
-            Rmessage::Rename => Ok(()),
-            Rmessage::Readlink(ref readlink) => readlink.encode(writer),
-            Rmessage::GetAttr(ref getattr) => getattr.encode(writer),
-            Rmessage::SetAttr => Ok(()),
-            Rmessage::XattrWalk(ref xattrwalk) => xattrwalk.encode(writer),
-            Rmessage::XattrCreate => Ok(()),
-            Rmessage::Readdir(ref readdir) => readdir.encode(writer),
-            Rmessage::Fsync => Ok(()),
-            Rmessage::Lock(ref lock) => lock.encode(writer),
-            Rmessage::GetLock(ref getlock) => getlock.encode(writer),
-            Rmessage::Link => Ok(()),
-            Rmessage::Mkdir(ref mkdir) => mkdir.encode(writer),
-            Rmessage::RenameAt => Ok(()),
-            Rmessage::UnlinkAt => Ok(()),
-            Rmessage::Lerror(ref lerror) => lerror.encode(writer),
-        }
-    }
-
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-        let byte_size: u32 = WireFormat::decode(reader)?;
-
-        // byte_size includes the size of byte_size so remove that from the
-        // expected length of the message.
-        let reader = &mut reader.take((byte_size - mem::size_of::<u32>() as u32) as u64);
-
-        let mut ty = [0u8];
-        reader.read_exact(&mut ty)?;
-
-        let tag: u16 = WireFormat::decode(reader)?;
-
-        let msg = match ty[0] {
-            RVERSION => Ok(Rmessage::Version(WireFormat::decode(reader)?)),
-            RFLUSH => Ok(Rmessage::Flush),
-            RWALK => Ok(Rmessage::Walk(WireFormat::decode(reader)?)),
-            RREAD => Ok(Rmessage::Read(WireFormat::decode(reader)?)),
-            RWRITE => Ok(Rmessage::Write(WireFormat::decode(reader)?)),
-            RCLUNK => Ok(Rmessage::Clunk),
-            RREMOVE => Ok(Rmessage::Remove),
-            RATTACH => Ok(Rmessage::Attach(WireFormat::decode(reader)?)),
-            RAUTH => Ok(Rmessage::Auth(WireFormat::decode(reader)?)),
-            RSTATFS => Ok(Rmessage::Statfs(WireFormat::decode(reader)?)),
-            RLOPEN => Ok(Rmessage::Lopen(WireFormat::decode(reader)?)),
-            RLCREATE => Ok(Rmessage::Lcreate(WireFormat::decode(reader)?)),
-            RSYMLINK => Ok(Rmessage::Symlink(WireFormat::decode(reader)?)),
-            RMKNOD => Ok(Rmessage::Mknod(WireFormat::decode(reader)?)),
-            RRENAME => Ok(Rmessage::Rename),
-            RREADLINK => Ok(Rmessage::Readlink(WireFormat::decode(reader)?)),
-            RGETATTR => Ok(Rmessage::GetAttr(WireFormat::decode(reader)?)),
-            RSETATTR => Ok(Rmessage::SetAttr),
-            RXATTRWALK => Ok(Rmessage::XattrWalk(WireFormat::decode(reader)?)),
-            RXATTRCREATE => Ok(Rmessage::XattrCreate),
-            RREADDIR => Ok(Rmessage::Readdir(WireFormat::decode(reader)?)),
-            RFSYNC => Ok(Rmessage::Fsync),
-            RLOCK => Ok(Rmessage::Lock(WireFormat::decode(reader)?)),
-            RGETLOCK => Ok(Rmessage::GetLock(WireFormat::decode(reader)?)),
-            RLINK => Ok(Rmessage::Link),
-            RMKDIR => Ok(Rmessage::Mkdir(WireFormat::decode(reader)?)),
-            RRENAMEAT => Ok(Rmessage::RenameAt),
-            RUNLINKAT => Ok(Rmessage::UnlinkAt),
-            RLERROR => Ok(Rmessage::Lerror(WireFormat::decode(reader)?)),
-            err => Err(io::Error::new(
-                ErrorKind::InvalidData,
-                format!("unknown message type {}", err),
-            )),
-        }?;
-
-        Ok(Rframe { tag, msg })
-    }
-}
-
-#[derive(Debug, Copy, Clone, P9WireFormat)]
-pub struct Qid {
-    pub ty: u8,
-    pub version: u32,
-    pub path: u64,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Dirent {
-    pub qid: Qid,
-    pub offset: u64,
-    pub ty: u8,
-    pub name: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rversion {
-    pub msize: u32,
-    pub version: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rwalk {
-    pub wqids: Vec<Qid>,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rread {
-    pub data: Data,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rwrite {
-    pub count: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rauth {
-    pub aqid: Qid,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rattach {
-    pub qid: Qid,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rlerror {
-    pub ecode: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rstatfs {
-    pub ty: u32,
-    pub bsize: u32,
-    pub blocks: u64,
-    pub bfree: u64,
-    pub bavail: u64,
-    pub files: u64,
-    pub ffree: u64,
-    pub fsid: u64,
-    pub namelen: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rlopen {
-    pub qid: Qid,
-    pub iounit: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rlcreate {
-    pub qid: Qid,
-    pub iounit: u32,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rsymlink {
-    pub qid: Qid,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rmknod {
-    pub qid: Qid,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rreadlink {
-    pub target: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rgetattr {
-    pub valid: u64,
-    pub qid: Qid,
-    pub mode: u32,
-    pub uid: u32,
-    pub gid: u32,
-    pub nlink: u64,
-    pub rdev: u64,
-    pub size: u64,
-    pub blksize: u64,
-    pub blocks: u64,
-    pub atime_sec: u64,
-    pub atime_nsec: u64,
-    pub mtime_sec: u64,
-    pub mtime_nsec: u64,
-    pub ctime_sec: u64,
-    pub ctime_nsec: u64,
-    pub btime_sec: u64,
-    pub btime_nsec: u64,
-    pub gen: u64,
-    pub data_version: u64,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rxattrwalk {
-    pub size: u64,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rreaddir {
-    pub data: Data,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rlock {
-    pub status: u8,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rgetlock {
-    pub ty: u8,
-    pub start: u64,
-    pub length: u64,
-    pub proc_id: u32,
-    pub client_id: String,
-}
-
-#[derive(Debug, P9WireFormat)]
-pub struct Rmkdir {
-    pub qid: Qid,
-}
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
deleted file mode 100644
index 9c278ee..0000000
--- a/src/protocol/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-mod messages;
-mod wire_format;
-
-pub use self::messages::*;
-pub use self::wire_format::{Data, WireFormat};
diff --git a/src/protocol/wire_format.rs b/src/protocol/wire_format.rs
deleted file mode 100644
index 7120937..0000000
--- a/src/protocol/wire_format.rs
+++ /dev/null
@@ -1,704 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use std::fmt;
-use std::io;
-use std::io::{ErrorKind, Read, Write};
-use std::mem;
-use std::ops::{Deref, DerefMut};
-use std::string::String;
-use std::vec::Vec;
-
-/// A type that can be encoded on the wire using the 9P protocol.
-pub trait WireFormat: std::marker::Sized {
-    /// Returns the number of bytes necessary to fully encode `self`.
-    fn byte_size(&self) -> u32;
-
-    /// Encodes `self` into `writer`.
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()>;
-
-    /// Decodes `Self` from `reader`.
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self>;
-}
-
-// This doesn't really _need_ to be a macro but unfortunately there is no trait bound to
-// express "can be casted to another type", which means we can't write `T as u8` in a trait
-// based implementation.  So instead we have this macro, which is implemented for all the
-// stable unsigned types with the added benefit of not being implemented for the signed
-// types which are not allowed by the protocol.
-macro_rules! uint_wire_format_impl {
-    ($Ty:ty) => {
-        impl WireFormat for $Ty {
-            fn byte_size(&self) -> u32 {
-                mem::size_of::<$Ty>() as u32
-            }
-
-            fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-                let mut buf = [0u8; mem::size_of::<$Ty>()];
-
-                // Encode the bytes into the buffer in little endian order.
-                for idx in 0..mem::size_of::<$Ty>() {
-                    buf[idx] = (self >> (8 * idx)) as u8;
-                }
-
-                writer.write_all(&buf)
-            }
-
-            fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-                let mut buf = [0u8; mem::size_of::<$Ty>()];
-                reader.read_exact(&mut buf)?;
-
-                // Read bytes from the buffer in little endian order.
-                let mut result = 0;
-                for idx in 0..mem::size_of::<$Ty>() {
-                    result |= (buf[idx] as $Ty) << (8 * idx);
-                }
-
-                Ok(result)
-            }
-        }
-    };
-}
-uint_wire_format_impl!(u8);
-uint_wire_format_impl!(u16);
-uint_wire_format_impl!(u32);
-uint_wire_format_impl!(u64);
-
-// The 9P protocol requires that strings are UTF-8 encoded.  The wire format is a u16
-// count |N|, encoded in little endian, followed by |N| bytes of UTF-8 data.
-impl WireFormat for String {
-    fn byte_size(&self) -> u32 {
-        (mem::size_of::<u16>() + self.len()) as u32
-    }
-
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-        if self.len() > std::u16::MAX as usize {
-            return Err(io::Error::new(
-                ErrorKind::InvalidInput,
-                "string is too long",
-            ));
-        }
-
-        (self.len() as u16).encode(writer)?;
-        writer.write_all(self.as_bytes())
-    }
-
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-        let len: u16 = WireFormat::decode(reader)?;
-        let mut result = String::with_capacity(len as usize);
-        reader.take(len as u64).read_to_string(&mut result)?;
-        Ok(result)
-    }
-}
-
-// The wire format for repeated types is similar to that of strings: a little endian
-// encoded u16 |N|, followed by |N| instances of the given type.
-impl<T: WireFormat> WireFormat for Vec<T> {
-    fn byte_size(&self) -> u32 {
-        mem::size_of::<u16>() as u32 + self.iter().map(|elem| elem.byte_size()).sum::<u32>()
-    }
-
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-        if self.len() > std::u16::MAX as usize {
-            return Err(io::Error::new(
-                ErrorKind::InvalidInput,
-                "too many elements in vector",
-            ));
-        }
-
-        (self.len() as u16).encode(writer)?;
-        for elem in self {
-            elem.encode(writer)?;
-        }
-
-        Ok(())
-    }
-
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-        let len: u16 = WireFormat::decode(reader)?;
-        let mut result = Vec::with_capacity(len as usize);
-
-        for _ in 0..len {
-            result.push(WireFormat::decode(reader)?);
-        }
-
-        Ok(result)
-    }
-}
-
-/// A type that encodes an arbitrary number of bytes of data.  Typically used for Rread
-/// Twrite messages.  This differs from a `Vec<u8>` in that it encodes the number of bytes
-/// using a `u32` instead of a `u16`.
-#[derive(PartialEq)]
-pub struct Data(pub Vec<u8>);
-
-// The maximum length of a data buffer that we support.  In practice the server's max message
-// size should prevent us from reading too much data so this check is mainly to ensure a
-// malicious client cannot trick us into allocating massive amounts of memory.
-const MAX_DATA_LENGTH: u32 = 32 * 1024 * 1024;
-
-impl fmt::Debug for Data {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // There may be a lot of data and we don't want to spew it all out in a trace.  Instead
-        // just print out the number of bytes in the buffer.
-        write!(f, "Data({} bytes)", self.len())
-    }
-}
-
-// Implement Deref and DerefMut so that we don't have to use self.0 everywhere.
-impl Deref for Data {
-    type Target = Vec<u8>;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-impl DerefMut for Data {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.0
-    }
-}
-
-// Same as Vec<u8> except that it encodes the length as a u32 instead of a u16.
-impl WireFormat for Data {
-    fn byte_size(&self) -> u32 {
-        mem::size_of::<u32>() as u32 + self.iter().map(|elem| elem.byte_size()).sum::<u32>()
-    }
-
-    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
-        if self.len() > std::u32::MAX as usize {
-            return Err(io::Error::new(ErrorKind::InvalidInput, "data is too large"));
-        }
-        (self.len() as u32).encode(writer)?;
-        writer.write_all(self)
-    }
-
-    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
-        let len: u32 = WireFormat::decode(reader)?;
-        if len > MAX_DATA_LENGTH {
-            return Err(io::Error::new(
-                ErrorKind::InvalidData,
-                format!("data length ({} bytes) is too large", len),
-            ));
-        }
-
-        let mut buf = Vec::with_capacity(len as usize);
-        reader.take(len as u64).read_to_end(&mut buf)?;
-
-        if buf.len() == len as usize {
-            Ok(Data(buf))
-        } else {
-            Err(io::Error::new(
-                ErrorKind::UnexpectedEof,
-                format!(
-                    "unexpected end of data: want: {} bytes, got: {} bytes",
-                    len,
-                    buf.len()
-                ),
-            ))
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use std::io::Cursor;
-    use std::mem;
-    use std::string::String;
-
-    #[test]
-    fn integer_byte_size() {
-        assert_eq!(1, 0u8.byte_size());
-        assert_eq!(2, 0u16.byte_size());
-        assert_eq!(4, 0u32.byte_size());
-        assert_eq!(8, 0u64.byte_size());
-    }
-
-    #[test]
-    fn integer_decode() {
-        let buf: [u8; 8] = [0xef, 0xbe, 0xad, 0xde, 0x0d, 0xf0, 0xad, 0x8b];
-
-        assert_eq!(
-            0xef as u8,
-            WireFormat::decode(&mut Cursor::new(&buf)).unwrap()
-        );
-        assert_eq!(0xbeef as u16, u16::decode(&mut Cursor::new(&buf)).unwrap());
-        assert_eq!(
-            0xdeadbeef as u32,
-            u32::decode(&mut Cursor::new(&buf)).unwrap()
-        );
-        assert_eq!(
-            0x8badf00d_deadbeef as u64,
-            u64::decode(&mut Cursor::new(&buf)).unwrap()
-        );
-    }
-
-    #[test]
-    fn integer_encode() {
-        let value: u64 = 0x8badf00d_deadbeef;
-        let expected: [u8; 8] = [0xef, 0xbe, 0xad, 0xde, 0x0d, 0xf0, 0xad, 0x8b];
-
-        let mut buf = vec![0; 8];
-
-        (value as u8).encode(&mut Cursor::new(&mut *buf)).unwrap();
-        assert_eq!(expected[0..1], buf[0..1]);
-
-        (value as u16).encode(&mut Cursor::new(&mut *buf)).unwrap();
-        assert_eq!(expected[0..2], buf[0..2]);
-
-        (value as u32).encode(&mut Cursor::new(&mut *buf)).unwrap();
-        assert_eq!(expected[0..4], buf[0..4]);
-
-        value.encode(&mut Cursor::new(&mut *buf)).unwrap();
-        assert_eq!(expected[0..8], buf[0..8]);
-    }
-
-    #[test]
-    fn string_byte_size() {
-        let values = [
-            String::from("Google Video"),
-            String::from("网页 图片 资讯更多 »"),
-            String::from("Παγκόσμιος Ιστός"),
-            String::from("Поиск страниц на русском"),
-            String::from("전체서비스"),
-        ];
-
-        let exp = values
-            .iter()
-            .map(|v| (mem::size_of::<u16>() + v.len()) as u32);
-
-        for (value, expected) in values.iter().zip(exp) {
-            assert_eq!(expected, value.byte_size());
-        }
-    }
-
-    #[test]
-    fn zero_length_string() {
-        let s = String::from("");
-        assert_eq!(s.byte_size(), mem::size_of::<u16>() as u32);
-
-        let mut buf = [0xffu8; 4];
-
-        s.encode(&mut Cursor::new(&mut buf[..]))
-            .expect("failed to encode empty string");
-        assert_eq!(&[0, 0, 0xff, 0xff], &buf);
-
-        assert_eq!(
-            s,
-            <String as WireFormat>::decode(&mut Cursor::new(&[0, 0, 0x61, 0x61][..]))
-                .expect("failed to decode empty string")
-        );
-    }
-
-    #[test]
-    fn string_encode() {
-        let values = [
-            String::from("Google Video"),
-            String::from("网页 图片 资讯更多 »"),
-            String::from("Παγκόσμιος Ιστός"),
-            String::from("Поиск страниц на русском"),
-            String::from("전체서비스"),
-        ];
-
-        let expected = values.iter().map(|v| {
-            let len = v.as_bytes().len();
-            let mut buf = Vec::with_capacity(len + mem::size_of::<u16>());
-
-            buf.push(len as u8);
-            buf.push((len >> 8) as u8);
-
-            buf.extend_from_slice(v.as_bytes());
-
-            buf
-        });
-
-        for (val, exp) in values.iter().zip(expected) {
-            let mut buf = vec![0; exp.len()];
-
-            WireFormat::encode(val, &mut Cursor::new(&mut *buf)).unwrap();
-            assert_eq!(exp, buf);
-        }
-    }
-
-    #[test]
-    fn string_decode() {
-        assert_eq!(
-            String::from("Google Video"),
-            <String as WireFormat>::decode(&mut Cursor::new(
-                &[
-                    0x0c, 0x00, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x56, 0x69, 0x64, 0x65,
-                    0x6F,
-                ][..]
-            ))
-            .unwrap()
-        );
-        assert_eq!(
-            String::from("网页 图片 资讯更多 »"),
-            <String as WireFormat>::decode(&mut Cursor::new(
-                &[
-                    0x1d, 0x00, 0xE7, 0xBD, 0x91, 0xE9, 0xA1, 0xB5, 0x20, 0xE5, 0x9B, 0xBE, 0xE7,
-                    0x89, 0x87, 0x20, 0xE8, 0xB5, 0x84, 0xE8, 0xAE, 0xAF, 0xE6, 0x9B, 0xB4, 0xE5,
-                    0xA4, 0x9A, 0x20, 0xC2, 0xBB,
-                ][..]
-            ))
-            .unwrap()
-        );
-        assert_eq!(
-            String::from("Παγκόσμιος Ιστός"),
-            <String as WireFormat>::decode(&mut Cursor::new(
-                &[
-                    0x1f, 0x00, 0xCE, 0xA0, 0xCE, 0xB1, 0xCE, 0xB3, 0xCE, 0xBA, 0xCF, 0x8C, 0xCF,
-                    0x83, 0xCE, 0xBC, 0xCE, 0xB9, 0xCE, 0xBF, 0xCF, 0x82, 0x20, 0xCE, 0x99, 0xCF,
-                    0x83, 0xCF, 0x84, 0xCF, 0x8C, 0xCF, 0x82,
-                ][..]
-            ))
-            .unwrap()
-        );
-        assert_eq!(
-            String::from("Поиск страниц на русском"),
-            <String as WireFormat>::decode(&mut Cursor::new(
-                &[
-                    0x2d, 0x00, 0xD0, 0x9F, 0xD0, 0xBE, 0xD0, 0xB8, 0xD1, 0x81, 0xD0, 0xBA, 0x20,
-                    0xD1, 0x81, 0xD1, 0x82, 0xD1, 0x80, 0xD0, 0xB0, 0xD0, 0xBD, 0xD0, 0xB8, 0xD1,
-                    0x86, 0x20, 0xD0, 0xBD, 0xD0, 0xB0, 0x20, 0xD1, 0x80, 0xD1, 0x83, 0xD1, 0x81,
-                    0xD1, 0x81, 0xD0, 0xBA, 0xD0, 0xBE, 0xD0, 0xBC,
-                ][..]
-            ))
-            .unwrap()
-        );
-        assert_eq!(
-            String::from("전체서비스"),
-            <String as WireFormat>::decode(&mut Cursor::new(
-                &[
-                    0x0f, 0x00, 0xEC, 0xA0, 0x84, 0xEC, 0xB2, 0xB4, 0xEC, 0x84, 0x9C, 0xEB, 0xB9,
-                    0x84, 0xEC, 0x8A, 0xA4,
-                ][..]
-            ))
-            .unwrap()
-        );
-    }
-
-    #[test]
-    fn invalid_string_decode() {
-        let _ = <String as WireFormat>::decode(&mut Cursor::new(&[
-            0x06, 0x00, 0xed, 0xa0, 0x80, 0xed, 0xbf, 0xbf,
-        ]))
-        .expect_err("surrogate code point");
-
-        let _ = <String as WireFormat>::decode(&mut Cursor::new(&[
-            0x05, 0x00, 0xf8, 0x80, 0x80, 0x80, 0xbf,
-        ]))
-        .expect_err("overlong sequence");
-
-        let _ =
-            <String as WireFormat>::decode(&mut Cursor::new(&[0x04, 0x00, 0xf4, 0x90, 0x80, 0x80]))
-                .expect_err("out of range");
-
-        let _ =
-            <String as WireFormat>::decode(&mut Cursor::new(&[0x04, 0x00, 0x63, 0x61, 0x66, 0xe9]))
-                .expect_err("ISO-8859-1");
-
-        let _ =
-            <String as WireFormat>::decode(&mut Cursor::new(&[0x04, 0x00, 0xb0, 0xa1, 0xb0, 0xa2]))
-                .expect_err("EUC-KR");
-    }
-
-    #[test]
-    fn vector_encode() {
-        let values: Vec<u32> = vec![291, 18_916, 2_497, 22, 797_162, 2_119_732, 3_213_929_716];
-        let mut expected: Vec<u8> =
-            Vec::with_capacity(values.len() * mem::size_of::<u32>() + mem::size_of::<u16>());
-        expected.push(values.len() as u8);
-        expected.push((values.len() >> 8) as u8);
-
-        const MASK: u32 = 0xff;
-        for val in &values {
-            expected.push((val & MASK) as u8);
-            expected.push(((val >> 8) & MASK) as u8);
-            expected.push(((val >> 16) & MASK) as u8);
-            expected.push(((val >> 24) & MASK) as u8);
-        }
-
-        let mut actual: Vec<u8> = vec![0; expected.len()];
-
-        WireFormat::encode(&values, &mut Cursor::new(&mut *actual))
-            .expect("failed to encode vector");
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn vector_decode() {
-        let expected: Vec<u32> = vec![
-            2_498,
-            24,
-            897,
-            4_097_789_579,
-            8_498_119,
-            684_279,
-            961_189_198,
-            7,
-        ];
-        let mut input: Vec<u8> =
-            Vec::with_capacity(expected.len() * mem::size_of::<u32>() + mem::size_of::<u16>());
-        input.push(expected.len() as u8);
-        input.push((expected.len() >> 8) as u8);
-
-        const MASK: u32 = 0xff;
-        for val in &expected {
-            input.push((val & MASK) as u8);
-            input.push(((val >> 8) & MASK) as u8);
-            input.push(((val >> 16) & MASK) as u8);
-            input.push(((val >> 24) & MASK) as u8);
-        }
-
-        assert_eq!(
-            expected,
-            <Vec<u32> as WireFormat>::decode(&mut Cursor::new(&*input))
-                .expect("failed to decode vector")
-        );
-    }
-
-    #[test]
-    fn data_encode() {
-        let values = Data(vec![169, 155, 79, 67, 182, 199, 25, 73, 129, 200]);
-        let mut expected: Vec<u8> =
-            Vec::with_capacity(values.len() * mem::size_of::<u8>() + mem::size_of::<u32>());
-        expected.push(values.len() as u8);
-        expected.push((values.len() >> 8) as u8);
-        expected.push((values.len() >> 16) as u8);
-        expected.push((values.len() >> 24) as u8);
-        expected.extend_from_slice(&values);
-
-        let mut actual: Vec<u8> = vec![0; expected.len()];
-
-        WireFormat::encode(&values, &mut Cursor::new(&mut *actual))
-            .expect("failed to encode datar");
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn data_decode() {
-        let expected = Data(vec![219, 15, 8, 155, 194, 129, 79, 91, 46, 53, 173]);
-        let mut input: Vec<u8> =
-            Vec::with_capacity(expected.len() * mem::size_of::<u8>() + mem::size_of::<u32>());
-        input.push(expected.len() as u8);
-        input.push((expected.len() >> 8) as u8);
-        input.push((expected.len() >> 16) as u8);
-        input.push((expected.len() >> 24) as u8);
-        input.extend_from_slice(&expected);
-
-        assert_eq!(
-            expected,
-            <Data as WireFormat>::decode(&mut Cursor::new(&mut *input))
-                .expect("failed to decode data")
-        );
-    }
-
-    #[test]
-    fn error_cases() {
-        // string is too long.
-        let mut long_str = String::with_capacity(std::u16::MAX as usize);
-        while long_str.len() < std::u16::MAX as usize {
-            long_str.push_str("long");
-        }
-        long_str.push_str("!");
-
-        let count = long_str.len() + mem::size_of::<u16>();
-        let mut buf = vec![0; count];
-
-        long_str
-            .encode(&mut Cursor::new(&mut *buf))
-            .expect_err("long string");
-
-        // vector is too long.
-        let mut long_vec: Vec<u32> = Vec::with_capacity(std::u16::MAX as usize);
-        while long_vec.len() < std::u16::MAX as usize {
-            long_vec.push(0x8bad_f00d);
-        }
-        long_vec.push(0x00ba_b10c);
-
-        let count = long_vec.len() * mem::size_of::<u32>();
-        let mut buf = vec![0; count];
-
-        WireFormat::encode(&long_vec, &mut Cursor::new(&mut *buf)).expect_err("long vector");
-    }
-
-    #[derive(Debug, PartialEq, P9WireFormat)]
-    struct Item {
-        a: u64,
-        b: String,
-        c: Vec<u16>,
-        buf: Data,
-    }
-
-    #[test]
-    fn struct_encode() {
-        let item = Item {
-            a: 0xdead10cc_00bab10c,
-            b: String::from("冻住,不许走!"),
-            c: vec![359, 492, 8891],
-            buf: Data(vec![254, 129, 0, 62, 49, 172]),
-        };
-
-        let mut expected: Vec<u8> = vec![0x0c, 0xb1, 0xba, 0x00, 0xcc, 0x10, 0xad, 0xde];
-        let strlen = item.b.len() as u16;
-        expected.push(strlen as u8);
-        expected.push((strlen >> 8) as u8);
-        expected.extend_from_slice(item.b.as_bytes());
-
-        let veclen = item.c.len() as u16;
-        expected.push(veclen as u8);
-        expected.push((veclen >> 8) as u8);
-        for val in &item.c {
-            expected.push(*val as u8);
-            expected.push((val >> 8) as u8);
-        }
-
-        let buflen = item.buf.len() as u32;
-        expected.push(buflen as u8);
-        expected.push((buflen >> 8) as u8);
-        expected.push((buflen >> 16) as u8);
-        expected.push((buflen >> 24) as u8);
-        expected.extend_from_slice(&item.buf);
-
-        let mut actual = vec![0; expected.len()];
-
-        WireFormat::encode(&item, &mut Cursor::new(&mut *actual)).expect("failed to encode item");
-
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn struct_decode() {
-        let expected = Item {
-            a: 0xface_b00c_0404_4b1d,
-            b: String::from("Огонь по готовности!"),
-            c: vec![20067, 32449, 549, 4972, 77, 1987],
-            buf: Data(vec![126, 236, 79, 59, 6, 159]),
-        };
-
-        let mut input: Vec<u8> = vec![0x1d, 0x4b, 0x04, 0x04, 0x0c, 0xb0, 0xce, 0xfa];
-        let strlen = expected.b.len() as u16;
-        input.push(strlen as u8);
-        input.push((strlen >> 8) as u8);
-        input.extend_from_slice(expected.b.as_bytes());
-
-        let veclen = expected.c.len() as u16;
-        input.push(veclen as u8);
-        input.push((veclen >> 8) as u8);
-        for val in &expected.c {
-            input.push(*val as u8);
-            input.push((val >> 8) as u8);
-        }
-
-        let buflen = expected.buf.len() as u32;
-        input.push(buflen as u8);
-        input.push((buflen >> 8) as u8);
-        input.push((buflen >> 16) as u8);
-        input.push((buflen >> 24) as u8);
-        input.extend_from_slice(&expected.buf);
-
-        let actual: Item =
-            WireFormat::decode(&mut Cursor::new(input)).expect("failed to decode item");
-
-        assert_eq!(expected, actual);
-    }
-
-    #[derive(Debug, PartialEq, P9WireFormat)]
-    struct Nested {
-        item: Item,
-        val: Vec<u64>,
-    }
-
-    fn build_encoded_buffer(value: &Nested) -> Vec<u8> {
-        let mut result: Vec<u8> = Vec::new();
-
-        // encode a
-        result.push(value.item.a as u8);
-        result.push((value.item.a >> 8) as u8);
-        result.push((value.item.a >> 16) as u8);
-        result.push((value.item.a >> 24) as u8);
-        result.push((value.item.a >> 32) as u8);
-        result.push((value.item.a >> 40) as u8);
-        result.push((value.item.a >> 48) as u8);
-        result.push((value.item.a >> 56) as u8);
-
-        // encode b
-        result.push(value.item.b.len() as u8);
-        result.push((value.item.b.len() >> 8) as u8);
-        result.extend_from_slice(value.item.b.as_bytes());
-
-        // encode c
-        result.push(value.item.c.len() as u8);
-        result.push((value.item.c.len() >> 8) as u8);
-        for val in &value.item.c {
-            result.push((val & 0xffu16) as u8);
-            result.push(((val >> 8) & 0xffu16) as u8);
-        }
-
-        // encode buf
-        result.push(value.item.buf.len() as u8);
-        result.push((value.item.buf.len() >> 8) as u8);
-        result.push((value.item.buf.len() >> 16) as u8);
-        result.push((value.item.buf.len() >> 24) as u8);
-        result.extend_from_slice(&value.item.buf);
-
-        // encode val
-        result.push(value.val.len() as u8);
-        result.push((value.val.len() >> 8) as u8);
-        for val in &value.val {
-            result.push(*val as u8);
-            result.push((val >> 8) as u8);
-            result.push((val >> 16) as u8);
-            result.push((val >> 24) as u8);
-            result.push((val >> 32) as u8);
-            result.push((val >> 40) as u8);
-            result.push((val >> 48) as u8);
-            result.push((val >> 56) as u8);
-        }
-
-        result
-    }
-
-    #[test]
-    fn nested_encode() {
-        let value = Nested {
-            item: Item {
-                a: 0xcafe_d00d_8bad_f00d,
-                b: String::from("龍が我が敵を喰らう!"),
-                c: vec![2679, 55_919, 44, 38_819, 792],
-                buf: Data(vec![129, 55, 200, 93, 7, 68]),
-            },
-            val: vec![1954978, 59, 4519, 15679],
-        };
-
-        let expected = build_encoded_buffer(&value);
-
-        let mut actual = vec![0; expected.len()];
-
-        WireFormat::encode(&value, &mut Cursor::new(&mut *actual)).expect("failed to encode value");
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn nested_decode() {
-        let expected = Nested {
-            item: Item {
-                a: 0x0ff1ce,
-                b: String::from("龍神の剣を喰らえ!"),
-                c: vec![21687, 159, 55, 9217, 192],
-                buf: Data(vec![189, 22, 7, 59, 235]),
-            },
-            val: vec![15679, 8619196, 319746, 123957, 77, 0, 492],
-        };
-
-        let input = build_encoded_buffer(&expected);
-
-        assert_eq!(
-            expected,
-            <Nested as WireFormat>::decode(&mut Cursor::new(&*input))
-                .expect("failed to decode value")
-        );
-    }
-}
diff --git a/src/server/mod.rs b/src/server/mod.rs
deleted file mode 100644
index 880a998..0000000
--- a/src/server/mod.rs
+++ /dev/null
@@ -1,977 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use std::cmp::min;
-use std::collections::{btree_map, BTreeMap};
-use std::ffi::{CStr, CString};
-use std::fs::File;
-use std::io::{self, Cursor, Read, Write};
-use std::mem::{self, MaybeUninit};
-use std::ops::Deref;
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::fs::FileExt;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-use std::path::Path;
-
-use libchromeos::{read_dir, syscall};
-
-use crate::protocol::*;
-
-// Tlopen and Tlcreate flags.  Taken from "include/net/9p/9p.h" in the linux tree.
-const P9_RDONLY: u32 = 0o00000000;
-const P9_WRONLY: u32 = 0o00000001;
-const P9_RDWR: u32 = 0o00000002;
-const P9_NOACCESS: u32 = 0o00000003;
-const P9_CREATE: u32 = 0o00000100;
-const P9_EXCL: u32 = 0o00000200;
-const P9_NOCTTY: u32 = 0o00000400;
-const P9_TRUNC: u32 = 0o00001000;
-const P9_APPEND: u32 = 0o00002000;
-const P9_NONBLOCK: u32 = 0o00004000;
-const P9_DSYNC: u32 = 0o00010000;
-const P9_FASYNC: u32 = 0o00020000;
-const P9_DIRECT: u32 = 0o00040000;
-const P9_LARGEFILE: u32 = 0o00100000;
-const P9_DIRECTORY: u32 = 0o00200000;
-const P9_NOFOLLOW: u32 = 0o00400000;
-const P9_NOATIME: u32 = 0o01000000;
-const _P9_CLOEXEC: u32 = 0o02000000;
-const P9_SYNC: u32 = 0o04000000;
-
-// Mapping from 9P flags to libc flags.
-const MAPPED_FLAGS: [(u32, i32); 16] = [
-    (P9_WRONLY, libc::O_WRONLY),
-    (P9_RDWR, libc::O_RDWR),
-    (P9_CREATE, libc::O_CREAT),
-    (P9_EXCL, libc::O_EXCL),
-    (P9_NOCTTY, libc::O_NOCTTY),
-    (P9_TRUNC, libc::O_TRUNC),
-    (P9_APPEND, libc::O_APPEND),
-    (P9_NONBLOCK, libc::O_NONBLOCK),
-    (P9_DSYNC, libc::O_DSYNC),
-    (P9_FASYNC, 0), // Unsupported
-    (P9_DIRECT, libc::O_DIRECT),
-    (P9_LARGEFILE, libc::O_LARGEFILE),
-    (P9_DIRECTORY, libc::O_DIRECTORY),
-    (P9_NOFOLLOW, libc::O_NOFOLLOW),
-    (P9_NOATIME, libc::O_NOATIME),
-    (P9_SYNC, libc::O_SYNC),
-];
-
-// 9P Qid types.  Taken from "include/net/9p/9p.h" in the linux tree.
-const P9_QTDIR: u8 = 0x80;
-const _P9_QTAPPEND: u8 = 0x40;
-const _P9_QTEXCL: u8 = 0x20;
-const _P9_QTMOUNT: u8 = 0x10;
-const _P9_QTAUTH: u8 = 0x08;
-const _P9_QTTMP: u8 = 0x04;
-const P9_QTSYMLINK: u8 = 0x02;
-const _P9_QTLINK: u8 = 0x01;
-const P9_QTFILE: u8 = 0x00;
-
-// Bitmask values for the getattr request.
-const _P9_GETATTR_MODE: u64 = 0x00000001;
-const _P9_GETATTR_NLINK: u64 = 0x00000002;
-const _P9_GETATTR_UID: u64 = 0x00000004;
-const _P9_GETATTR_GID: u64 = 0x00000008;
-const _P9_GETATTR_RDEV: u64 = 0x00000010;
-const _P9_GETATTR_ATIME: u64 = 0x00000020;
-const _P9_GETATTR_MTIME: u64 = 0x00000040;
-const _P9_GETATTR_CTIME: u64 = 0x00000080;
-const _P9_GETATTR_INO: u64 = 0x00000100;
-const _P9_GETATTR_SIZE: u64 = 0x00000200;
-const _P9_GETATTR_BLOCKS: u64 = 0x00000400;
-
-const _P9_GETATTR_BTIME: u64 = 0x00000800;
-const _P9_GETATTR_GEN: u64 = 0x00001000;
-const _P9_GETATTR_DATA_VERSION: u64 = 0x00002000;
-
-const P9_GETATTR_BASIC: u64 = 0x000007ff; /* Mask for fields up to BLOCKS */
-const _P9_GETATTR_ALL: u64 = 0x00003fff; /* Mask for All fields above */
-
-// Bitmask values for the setattr request.
-const P9_SETATTR_MODE: u32 = 0x00000001;
-const P9_SETATTR_UID: u32 = 0x00000002;
-const P9_SETATTR_GID: u32 = 0x00000004;
-const P9_SETATTR_SIZE: u32 = 0x00000008;
-const P9_SETATTR_ATIME: u32 = 0x00000010;
-const P9_SETATTR_MTIME: u32 = 0x00000020;
-const P9_SETATTR_CTIME: u32 = 0x00000040;
-const P9_SETATTR_ATIME_SET: u32 = 0x00000080;
-const P9_SETATTR_MTIME_SET: u32 = 0x00000100;
-
-// Minimum and maximum message size that we'll expect from the client.
-const MIN_MESSAGE_SIZE: u32 = 256;
-const MAX_MESSAGE_SIZE: u32 = ::std::u16::MAX as u32;
-
-#[derive(PartialEq, Eq)]
-enum FileType {
-    Regular,
-    Directory,
-    Other,
-}
-
-impl From<libc::mode_t> for FileType {
-    fn from(mode: libc::mode_t) -> Self {
-        match mode & libc::S_IFMT {
-            libc::S_IFREG => FileType::Regular,
-            libc::S_IFDIR => FileType::Directory,
-            _ => FileType::Other,
-        }
-    }
-}
-
-// Represents state that the server is holding on behalf of a client. Fids are somewhat like file
-// descriptors but are not restricted to open files and directories. Fids are identified by a unique
-// 32-bit number chosen by the client. Most messages sent by clients include a fid on which to
-// operate. The fid in a Tattach message represents the root of the file system tree that the client
-// is allowed to access. A client can create more fids by walking the directory tree from that fid.
-struct Fid {
-    path: File,
-    file: Option<File>,
-    filetype: FileType,
-}
-
-impl From<libc::stat64> for Qid {
-    fn from(st: libc::stat64) -> Qid {
-        let ty = match st.st_mode & libc::S_IFMT {
-            libc::S_IFDIR => P9_QTDIR,
-            libc::S_IFREG => P9_QTFILE,
-            libc::S_IFLNK => P9_QTSYMLINK,
-            _ => 0,
-        };
-
-        Qid {
-            ty,
-            // TODO: deal with the 2038 problem before 2038
-            version: st.st_mtime as u32,
-            path: st.st_ino,
-        }
-    }
-}
-
-fn statat(d: &File, name: &CStr, flags: libc::c_int) -> io::Result<libc::stat64> {
-    let mut st = MaybeUninit::<libc::stat64>::zeroed();
-
-    // Safe because the kernel will only write data in `st` and we check the return
-    // value.
-    let res = unsafe {
-        libc::fstatat64(
-            d.as_raw_fd(),
-            name.as_ptr(),
-            st.as_mut_ptr(),
-            flags | libc::AT_SYMLINK_NOFOLLOW,
-        )
-    };
-    if res >= 0 {
-        // Safe because the kernel guarantees that the struct is now fully initialized.
-        Ok(unsafe { st.assume_init() })
-    } else {
-        Err(io::Error::last_os_error())
-    }
-}
-
-fn stat(f: &File) -> io::Result<libc::stat64> {
-    // Safe because this is a constant value and a valid C string.
-    let pathname = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") };
-
-    statat(f, pathname, libc::AT_EMPTY_PATH)
-}
-
-fn string_to_cstring(s: String) -> io::Result<CString> {
-    CString::new(s).map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))
-}
-
-fn error_to_rmessage(err: io::Error) -> Rmessage {
-    let errno = if let Some(errno) = err.raw_os_error() {
-        errno
-    } else {
-        // Make a best-effort guess based on the kind.
-        match err.kind() {
-            io::ErrorKind::NotFound => libc::ENOENT,
-            io::ErrorKind::PermissionDenied => libc::EPERM,
-            io::ErrorKind::ConnectionRefused => libc::ECONNREFUSED,
-            io::ErrorKind::ConnectionReset => libc::ECONNRESET,
-            io::ErrorKind::ConnectionAborted => libc::ECONNABORTED,
-            io::ErrorKind::NotConnected => libc::ENOTCONN,
-            io::ErrorKind::AddrInUse => libc::EADDRINUSE,
-            io::ErrorKind::AddrNotAvailable => libc::EADDRNOTAVAIL,
-            io::ErrorKind::BrokenPipe => libc::EPIPE,
-            io::ErrorKind::AlreadyExists => libc::EEXIST,
-            io::ErrorKind::WouldBlock => libc::EWOULDBLOCK,
-            io::ErrorKind::InvalidInput => libc::EINVAL,
-            io::ErrorKind::InvalidData => libc::EINVAL,
-            io::ErrorKind::TimedOut => libc::ETIMEDOUT,
-            io::ErrorKind::WriteZero => libc::EIO,
-            io::ErrorKind::Interrupted => libc::EINTR,
-            io::ErrorKind::Other => libc::EIO,
-            io::ErrorKind::UnexpectedEof => libc::EIO,
-            _ => libc::EIO,
-        }
-    };
-
-    Rmessage::Lerror(Rlerror {
-        ecode: errno as u32,
-    })
-}
-
-// Sigh.. Cow requires the underlying type to implement Clone.
-enum MaybeOwned<'b, T> {
-    Borrowed(&'b T),
-    Owned(T),
-}
-
-impl<'a, T> Deref for MaybeOwned<'a, T> {
-    type Target = T;
-    fn deref(&self) -> &Self::Target {
-        use MaybeOwned::*;
-        match *self {
-            Borrowed(borrowed) => borrowed,
-            Owned(ref owned) => owned,
-        }
-    }
-}
-
-fn ebadf() -> io::Error {
-    io::Error::from_raw_os_error(libc::EBADF)
-}
-
-pub type ServerIdMap<T> = BTreeMap<T, T>;
-pub type ServerUidMap = ServerIdMap<libc::uid_t>;
-pub type ServerGidMap = ServerIdMap<libc::gid_t>;
-
-fn map_id_from_host<T: Clone + Ord>(map: &ServerIdMap<T>, id: T) -> T {
-    map.get(&id).map_or(id.clone(), |v| v.clone())
-}
-
-// Performs an ascii case insensitive lookup and returns an O_PATH fd for the entry, if found.
-fn ascii_casefold_lookup(proc: &File, parent: &File, name: &[u8]) -> io::Result<File> {
-    let mut dir = open_fid(proc, &parent, P9_DIRECTORY)?;
-    let mut dirents = read_dir(&mut dir, 0)?;
-
-    while let Some(entry) = dirents.next().transpose()? {
-        if name.eq_ignore_ascii_case(entry.name.to_bytes()) {
-            return lookup(parent, entry.name);
-        }
-    }
-
-    Err(io::Error::from_raw_os_error(libc::ENOENT))
-}
-
-fn lookup(parent: &File, name: &CStr) -> io::Result<File> {
-    // Safe because this doesn't modify any memory and we check the return value.
-    let fd = syscall!(unsafe {
-        libc::openat(
-            parent.as_raw_fd(),
-            name.as_ptr(),
-            libc::O_PATH | libc::O_NOFOLLOW | libc::O_CLOEXEC,
-        )
-    })?;
-
-    // Safe because we just opened this fd.
-    Ok(unsafe { File::from_raw_fd(fd) })
-}
-
-fn do_walk(
-    proc: &File,
-    wnames: Vec<String>,
-    start: File,
-    ascii_casefold: bool,
-    mds: &mut Vec<libc::stat64>,
-) -> io::Result<File> {
-    let mut current = start;
-
-    for wname in wnames {
-        let name = string_to_cstring(wname)?;
-        current = lookup(&current, &name).or_else(|e| {
-            if ascii_casefold {
-                if let Some(libc::ENOENT) = e.raw_os_error() {
-                    return ascii_casefold_lookup(proc, &current, name.to_bytes());
-                }
-            }
-
-            Err(e)
-        })?;
-        mds.push(stat(&current)?);
-    }
-
-    Ok(current)
-}
-
-fn open_fid(proc: &File, path: &File, p9_flags: u32) -> io::Result<File> {
-    let pathname = string_to_cstring(format!("self/fd/{}", path.as_raw_fd()))?;
-
-    // We always open files with O_CLOEXEC.
-    let mut flags: i32 = libc::O_CLOEXEC;
-    for &(p9f, of) in &MAPPED_FLAGS {
-        if (p9_flags & p9f) != 0 {
-            flags |= of;
-        }
-    }
-
-    if p9_flags & P9_NOACCESS == P9_RDONLY {
-        flags |= libc::O_RDONLY;
-    }
-
-    // Safe because this doesn't modify any memory and we check the return value. We need to
-    // clear the O_NOFOLLOW flag because we want to follow the proc symlink.
-    let fd = syscall!(unsafe {
-        libc::openat(
-            proc.as_raw_fd(),
-            pathname.as_ptr(),
-            flags & !libc::O_NOFOLLOW,
-        )
-    })?;
-
-    // Safe because we just opened this fd and we know it is valid.
-    Ok(unsafe { File::from_raw_fd(fd) })
-}
-
-#[derive(Clone)]
-pub struct Config {
-    pub root: Box<Path>,
-    pub msize: u32,
-
-    pub uid_map: ServerUidMap,
-    pub gid_map: ServerGidMap,
-
-    pub ascii_casefold: bool,
-}
-
-impl Default for Config {
-    fn default() -> Config {
-        Config {
-            root: Path::new("/").into(),
-            msize: MAX_MESSAGE_SIZE,
-            uid_map: Default::default(),
-            gid_map: Default::default(),
-            ascii_casefold: false,
-        }
-    }
-}
-pub struct Server {
-    fids: BTreeMap<u32, Fid>,
-    proc: File,
-    cfg: Config,
-}
-
-impl Server {
-    pub fn new<P: Into<Box<Path>>>(
-        root: P,
-        uid_map: ServerUidMap,
-        gid_map: ServerGidMap,
-    ) -> io::Result<Server> {
-        Server::with_config(Config {
-            root: root.into(),
-            msize: MAX_MESSAGE_SIZE,
-            uid_map,
-            gid_map,
-            ascii_casefold: false,
-        })
-    }
-
-    pub fn with_config(cfg: Config) -> io::Result<Server> {
-        // Safe because this is a valid c-string.
-        let proc_cstr = unsafe { CStr::from_bytes_with_nul_unchecked(b"/proc\0") };
-
-        // Safe because this doesn't modify any memory and we check the return value.
-        let fd = syscall!(unsafe {
-            libc::openat(
-                libc::AT_FDCWD,
-                proc_cstr.as_ptr(),
-                libc::O_PATH | libc::O_NOFOLLOW | libc::O_CLOEXEC,
-            )
-        })?;
-
-        // Safe because we just opened this fd and we know it is valid.
-        let proc = unsafe { File::from_raw_fd(fd) };
-        Ok(Server {
-            fids: BTreeMap::new(),
-            proc,
-            cfg,
-        })
-    }
-
-    pub fn keep_fds(&self) -> Vec<RawFd> {
-        vec![self.proc.as_raw_fd()]
-    }
-
-    pub fn handle_message<R: Read, W: Write>(
-        &mut self,
-        reader: &mut R,
-        writer: &mut W,
-    ) -> io::Result<()> {
-        let Tframe { tag, msg } = WireFormat::decode(&mut reader.take(self.cfg.msize as u64))?;
-
-        let rmsg = match msg {
-            Tmessage::Version(ref version) => self.version(version).map(Rmessage::Version),
-            Tmessage::Flush(ref flush) => self.flush(flush).and(Ok(Rmessage::Flush)),
-            Tmessage::Walk(walk) => self.walk(walk).map(Rmessage::Walk),
-            Tmessage::Read(ref read) => self.read(read).map(Rmessage::Read),
-            Tmessage::Write(ref write) => self.write(write).map(Rmessage::Write),
-            Tmessage::Clunk(ref clunk) => self.clunk(clunk).and(Ok(Rmessage::Clunk)),
-            Tmessage::Remove(ref remove) => self.remove(remove).and(Ok(Rmessage::Remove)),
-            Tmessage::Attach(ref attach) => self.attach(attach).map(Rmessage::Attach),
-            Tmessage::Auth(ref auth) => self.auth(auth).map(Rmessage::Auth),
-            Tmessage::Statfs(ref statfs) => self.statfs(statfs).map(Rmessage::Statfs),
-            Tmessage::Lopen(ref lopen) => self.lopen(lopen).map(Rmessage::Lopen),
-            Tmessage::Lcreate(lcreate) => self.lcreate(lcreate).map(Rmessage::Lcreate),
-            Tmessage::Symlink(ref symlink) => self.symlink(symlink).map(Rmessage::Symlink),
-            Tmessage::Mknod(ref mknod) => self.mknod(mknod).map(Rmessage::Mknod),
-            Tmessage::Rename(ref rename) => self.rename(rename).and(Ok(Rmessage::Rename)),
-            Tmessage::Readlink(ref readlink) => self.readlink(readlink).map(Rmessage::Readlink),
-            Tmessage::GetAttr(ref get_attr) => self.get_attr(get_attr).map(Rmessage::GetAttr),
-            Tmessage::SetAttr(ref set_attr) => self.set_attr(set_attr).and(Ok(Rmessage::SetAttr)),
-            Tmessage::XattrWalk(ref xattr_walk) => {
-                self.xattr_walk(xattr_walk).map(Rmessage::XattrWalk)
-            }
-            Tmessage::XattrCreate(ref xattr_create) => self
-                .xattr_create(xattr_create)
-                .and(Ok(Rmessage::XattrCreate)),
-            Tmessage::Readdir(ref readdir) => self.readdir(readdir).map(Rmessage::Readdir),
-            Tmessage::Fsync(ref fsync) => self.fsync(fsync).and(Ok(Rmessage::Fsync)),
-            Tmessage::Lock(ref lock) => self.lock(lock).map(Rmessage::Lock),
-            Tmessage::GetLock(ref get_lock) => self.get_lock(get_lock).map(Rmessage::GetLock),
-            Tmessage::Link(link) => self.link(link).and(Ok(Rmessage::Link)),
-            Tmessage::Mkdir(mkdir) => self.mkdir(mkdir).map(Rmessage::Mkdir),
-            Tmessage::RenameAt(rename_at) => self.rename_at(rename_at).and(Ok(Rmessage::RenameAt)),
-            Tmessage::UnlinkAt(unlink_at) => self.unlink_at(unlink_at).and(Ok(Rmessage::UnlinkAt)),
-        };
-
-        // Errors while handling requests are never fatal.
-        let response = Rframe {
-            tag,
-            msg: rmsg.unwrap_or_else(error_to_rmessage),
-        };
-
-        response.encode(writer)?;
-        writer.flush()
-    }
-
-    fn auth(&mut self, _auth: &Tauth) -> io::Result<Rauth> {
-        // Returning an error for the auth message means that the server does not require
-        // authentication.
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn attach(&mut self, attach: &Tattach) -> io::Result<Rattach> {
-        // TODO: Check attach parameters
-        match self.fids.entry(attach.fid) {
-            btree_map::Entry::Vacant(entry) => {
-                let root = CString::new(self.cfg.root.as_os_str().as_bytes())
-                    .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
-
-                // Safe because this doesn't modify any memory and we check the return value.
-                let fd = syscall!(unsafe {
-                    libc::openat(
-                        libc::AT_FDCWD,
-                        root.as_ptr(),
-                        libc::O_PATH | libc::O_NOFOLLOW | libc::O_CLOEXEC,
-                    )
-                })?;
-
-                let root_path = unsafe { File::from_raw_fd(fd) };
-                let st = stat(&root_path)?;
-
-                let fid = Fid {
-                    // Safe because we just opened this fd.
-                    path: root_path,
-                    file: None,
-                    filetype: st.st_mode.into(),
-                };
-                let response = Rattach { qid: st.into() };
-                entry.insert(fid);
-                Ok(response)
-            }
-            btree_map::Entry::Occupied(_) => Err(io::Error::from_raw_os_error(libc::EBADF)),
-        }
-    }
-
-    fn version(&mut self, version: &Tversion) -> io::Result<Rversion> {
-        if version.msize < MIN_MESSAGE_SIZE {
-            return Err(io::Error::from_raw_os_error(libc::EINVAL));
-        }
-
-        // A Tversion request clunks all open fids and terminates any pending I/O.
-        self.fids.clear();
-        self.cfg.msize = min(self.cfg.msize, version.msize);
-
-        Ok(Rversion {
-            msize: self.cfg.msize,
-            version: if version.version == "9P2000.L" {
-                String::from("9P2000.L")
-            } else {
-                String::from("unknown")
-            },
-        })
-    }
-
-    fn flush(&mut self, _flush: &Tflush) -> io::Result<()> {
-        // TODO: Since everything is synchronous we can't actually flush requests.
-        Ok(())
-    }
-
-    fn walk(&mut self, walk: Twalk) -> io::Result<Rwalk> {
-        // `newfid` must not currently be in use unless it is the same as `fid`.
-        if walk.fid != walk.newfid && self.fids.contains_key(&walk.newfid) {
-            return Err(io::Error::from_raw_os_error(libc::EBADF));
-        }
-
-        // We need to walk the tree.  First get the starting path.
-        let start = self
-            .fids
-            .get(&walk.fid)
-            .ok_or_else(ebadf)
-            .and_then(|fid| fid.path.try_clone())?;
-
-        // Now walk the tree and break on the first error, if any.
-        let expected_len = walk.wnames.len();
-        let mut mds = Vec::with_capacity(expected_len);
-        match do_walk(
-            &self.proc,
-            walk.wnames,
-            start,
-            self.cfg.ascii_casefold,
-            &mut mds,
-        ) {
-            Ok(end) => {
-                // Store the new fid if the full walk succeeded.
-                if mds.len() == expected_len {
-                    let st = mds.last().copied().map(Ok).unwrap_or_else(|| stat(&end))?;
-                    self.fids.insert(
-                        walk.newfid,
-                        Fid {
-                            path: end,
-                            file: None,
-                            filetype: st.st_mode.into(),
-                        },
-                    );
-                }
-            }
-            Err(e) => {
-                // Only return an error if it occurred on the first component.
-                if mds.is_empty() {
-                    return Err(e);
-                }
-            }
-        }
-
-        Ok(Rwalk {
-            wqids: mds.into_iter().map(Qid::from).collect(),
-        })
-    }
-
-    fn read(&mut self, read: &Tread) -> io::Result<Rread> {
-        // Thankfully, `read` cannot be used to read directories in 9P2000.L.
-        let file = self
-            .fids
-            .get_mut(&read.fid)
-            .and_then(|fid| fid.file.as_mut())
-            .ok_or_else(ebadf)?;
-
-        // Use an empty Rread struct to figure out the overhead of the header.
-        let header_size = Rframe {
-            tag: 0,
-            msg: Rmessage::Read(Rread {
-                data: Data(Vec::new()),
-            }),
-        }
-        .byte_size();
-
-        let capacity = min(self.cfg.msize - header_size, read.count);
-        let mut buf = Data(vec![0u8; capacity as usize]);
-
-        let count = file.read_at(&mut buf, read.offset)?;
-        buf.truncate(count);
-
-        Ok(Rread { data: buf })
-    }
-
-    fn write(&mut self, write: &Twrite) -> io::Result<Rwrite> {
-        let file = self
-            .fids
-            .get_mut(&write.fid)
-            .and_then(|fid| fid.file.as_mut())
-            .ok_or_else(ebadf)?;
-
-        let count = file.write_at(&write.data, write.offset)?;
-        Ok(Rwrite {
-            count: count as u32,
-        })
-    }
-
-    fn clunk(&mut self, clunk: &Tclunk) -> io::Result<()> {
-        match self.fids.entry(clunk.fid) {
-            btree_map::Entry::Vacant(_) => Err(io::Error::from_raw_os_error(libc::EBADF)),
-            btree_map::Entry::Occupied(entry) => {
-                entry.remove();
-                Ok(())
-            }
-        }
-    }
-
-    fn remove(&mut self, _remove: &Tremove) -> io::Result<()> {
-        // Since a file could be linked into multiple locations, there is no way to know exactly
-        // which path we are supposed to unlink. Linux uses unlink_at anyway, so we can just return
-        // an error here.
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn statfs(&mut self, statfs: &Tstatfs) -> io::Result<Rstatfs> {
-        let fid = self.fids.get(&statfs.fid).ok_or_else(ebadf)?;
-        let mut buf = MaybeUninit::zeroed();
-
-        // Safe because this will only modify `out` and we check the return value.
-        syscall!(unsafe { libc::fstatfs64(fid.path.as_raw_fd(), buf.as_mut_ptr()) })?;
-
-        // Safe because this only has integer types and any value is valid.
-        let out = unsafe { buf.assume_init() };
-        Ok(Rstatfs {
-            ty: out.f_type as u32,
-            bsize: out.f_bsize as u32,
-            blocks: out.f_blocks,
-            bfree: out.f_bfree,
-            bavail: out.f_bavail,
-            files: out.f_files,
-            ffree: out.f_ffree,
-            // Safe because the fsid has only integer fields and the compiler will verify that is
-            // the same width as the `fsid` field in Rstatfs.
-            fsid: unsafe { mem::transmute(out.f_fsid) },
-            namelen: out.f_namelen as u32,
-        })
-    }
-
-    fn lopen(&mut self, lopen: &Tlopen) -> io::Result<Rlopen> {
-        let fid = self.fids.get_mut(&lopen.fid).ok_or_else(ebadf)?;
-
-        let file = open_fid(&self.proc, &fid.path, lopen.flags)?;
-        let st = stat(&file)?;
-
-        fid.file = Some(file);
-        let iounit = st.st_blksize as u32;
-        Ok(Rlopen {
-            qid: st.into(),
-            iounit,
-        })
-    }
-
-    fn lcreate(&mut self, lcreate: Tlcreate) -> io::Result<Rlcreate> {
-        let fid = self.fids.get_mut(&lcreate.fid).ok_or_else(ebadf)?;
-
-        if fid.filetype != FileType::Directory {
-            return Err(io::Error::from_raw_os_error(libc::ENOTDIR));
-        }
-
-        let mut flags: i32 = libc::O_CLOEXEC | libc::O_CREAT | libc::O_EXCL;
-        for &(p9f, of) in &MAPPED_FLAGS {
-            if (lcreate.flags & p9f) != 0 {
-                flags |= of;
-            }
-        }
-        if lcreate.flags & P9_NOACCESS == P9_RDONLY {
-            flags |= libc::O_RDONLY;
-        }
-
-        let name = string_to_cstring(lcreate.name)?;
-
-        // Safe because this doesn't modify any memory and we check the return value.
-        let fd = syscall!(unsafe {
-            libc::openat(fid.path.as_raw_fd(), name.as_ptr(), flags, lcreate.mode)
-        })?;
-
-        // Safe because we just opened this fd and we know it is valid.
-        let file = unsafe { File::from_raw_fd(fd) };
-        let st = stat(&file)?;
-        let iounit = st.st_blksize as u32;
-
-        fid.file = Some(file);
-
-        // This fid now refers to the newly created file so we need to update the O_PATH fd for it
-        // as well.
-        fid.path = lookup(&fid.path, &name)?;
-
-        Ok(Rlcreate {
-            qid: st.into(),
-            iounit,
-        })
-    }
-
-    fn symlink(&mut self, _symlink: &Tsymlink) -> io::Result<Rsymlink> {
-        // symlinks are not allowed.
-        Err(io::Error::from_raw_os_error(libc::EACCES))
-    }
-
-    fn mknod(&mut self, _mknod: &Tmknod) -> io::Result<Rmknod> {
-        // No nodes either.
-        Err(io::Error::from_raw_os_error(libc::EACCES))
-    }
-
-    fn rename(&mut self, _rename: &Trename) -> io::Result<()> {
-        // We cannot support this as an inode may be linked into multiple directories but we don't
-        // know which one the client wants us to rename. Linux uses rename_at anyway, so we don't
-        // need to worry about this.
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn readlink(&mut self, _readlink: &Treadlink) -> io::Result<Rreadlink> {
-        // symlinks are not allowed
-        Err(io::Error::from_raw_os_error(libc::EACCES))
-    }
-
-    fn get_attr(&mut self, get_attr: &Tgetattr) -> io::Result<Rgetattr> {
-        let fid = self.fids.get_mut(&get_attr.fid).ok_or_else(ebadf)?;
-
-        let st = stat(&fid.path)?;
-
-        Ok(Rgetattr {
-            valid: P9_GETATTR_BASIC,
-            qid: st.into(),
-            mode: st.st_mode,
-            uid: map_id_from_host(&self.cfg.uid_map, st.st_uid),
-            gid: map_id_from_host(&self.cfg.gid_map, st.st_gid),
-            nlink: st.st_nlink as u64,
-            rdev: st.st_rdev,
-            size: st.st_size as u64,
-            blksize: st.st_blksize as u64,
-            blocks: st.st_blocks as u64,
-            atime_sec: st.st_atime as u64,
-            atime_nsec: st.st_atime_nsec as u64,
-            mtime_sec: st.st_mtime as u64,
-            mtime_nsec: st.st_mtime_nsec as u64,
-            ctime_sec: st.st_ctime as u64,
-            ctime_nsec: st.st_ctime_nsec as u64,
-            btime_sec: 0,
-            btime_nsec: 0,
-            gen: 0,
-            data_version: 0,
-        })
-    }
-
-    fn set_attr(&mut self, set_attr: &Tsetattr) -> io::Result<()> {
-        let blocked_ops = P9_SETATTR_MODE | P9_SETATTR_UID | P9_SETATTR_GID;
-        if set_attr.valid & blocked_ops != 0 {
-            return Err(io::Error::from_raw_os_error(libc::EPERM));
-        }
-
-        let fid = self.fids.get(&set_attr.fid).ok_or_else(ebadf)?;
-
-        let file = if let Some(ref file) = fid.file {
-            MaybeOwned::Borrowed(file)
-        } else {
-            let flags = match fid.filetype {
-                FileType::Regular => P9_RDWR,
-                FileType::Directory => P9_RDONLY | P9_DIRECTORY,
-                FileType::Other => P9_RDWR,
-            };
-            MaybeOwned::Owned(open_fid(&self.proc, &fid.path, P9_NONBLOCK | flags)?)
-        };
-
-        if set_attr.valid & P9_SETATTR_SIZE != 0 {
-            file.set_len(set_attr.size)?;
-        }
-
-        if set_attr.valid & (P9_SETATTR_ATIME | P9_SETATTR_MTIME) != 0 {
-            let times = [
-                libc::timespec {
-                    tv_sec: set_attr.atime_sec as _,
-                    tv_nsec: if set_attr.valid & P9_SETATTR_ATIME == 0 {
-                        libc::UTIME_OMIT
-                    } else if set_attr.valid & P9_SETATTR_ATIME_SET == 0 {
-                        libc::UTIME_NOW
-                    } else {
-                        set_attr.atime_nsec as _
-                    },
-                },
-                libc::timespec {
-                    tv_sec: set_attr.mtime_sec as _,
-                    tv_nsec: if set_attr.valid & P9_SETATTR_MTIME == 0 {
-                        libc::UTIME_OMIT
-                    } else if set_attr.valid & P9_SETATTR_MTIME_SET == 0 {
-                        libc::UTIME_NOW
-                    } else {
-                        set_attr.mtime_nsec as _
-                    },
-                },
-            ];
-
-            // Safe because file is valid and we have initialized times fully.
-            let ret = unsafe { libc::futimens(file.as_raw_fd(), &times as *const libc::timespec) };
-            if ret < 0 {
-                return Err(io::Error::last_os_error());
-            }
-        }
-
-        // The ctime would have been updated by any of the above operations so we only
-        // need to change it if it was the only option given.
-        if set_attr.valid & P9_SETATTR_CTIME != 0 && set_attr.valid & (!P9_SETATTR_CTIME) == 0 {
-            // Setting -1 as the uid and gid will not actually change anything but will
-            // still update the ctime.
-            let ret = unsafe {
-                libc::fchown(
-                    file.as_raw_fd(),
-                    libc::uid_t::max_value(),
-                    libc::gid_t::max_value(),
-                )
-            };
-            if ret < 0 {
-                return Err(io::Error::last_os_error());
-            }
-        }
-
-        Ok(())
-    }
-
-    fn xattr_walk(&mut self, _xattr_walk: &Txattrwalk) -> io::Result<Rxattrwalk> {
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn xattr_create(&mut self, _xattr_create: &Txattrcreate) -> io::Result<()> {
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn readdir(&mut self, readdir: &Treaddir) -> io::Result<Rreaddir> {
-        let fid = self.fids.get_mut(&readdir.fid).ok_or_else(ebadf)?;
-
-        if fid.filetype != FileType::Directory {
-            return Err(io::Error::from_raw_os_error(libc::ENOTDIR));
-        }
-
-        // Use an empty Rreaddir struct to figure out the maximum number of bytes that
-        // can be returned.
-        let header_size = Rframe {
-            tag: 0,
-            msg: Rmessage::Readdir(Rreaddir {
-                data: Data(Vec::new()),
-            }),
-        }
-        .byte_size();
-        let count = min(self.cfg.msize - header_size, readdir.count);
-        let mut cursor = Cursor::new(Vec::with_capacity(count as usize));
-
-        let dir = fid.file.as_mut().ok_or_else(ebadf)?;
-        let mut dirents = read_dir(dir, readdir.offset as libc::off64_t)?;
-        while let Some(dirent) = dirents.next().transpose()? {
-            let st = statat(&fid.path, &dirent.name, 0)?;
-
-            let name = dirent
-                .name
-                .to_str()
-                .map(String::from)
-                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
-
-            let entry = Dirent {
-                qid: st.into(),
-                offset: dirent.offset,
-                ty: dirent.type_,
-                name,
-            };
-
-            let byte_size = entry.byte_size() as usize;
-
-            if cursor.get_ref().capacity() - cursor.get_ref().len() < byte_size {
-                // No more room in the buffer.
-                break;
-            }
-
-            entry.encode(&mut cursor)?;
-        }
-
-        Ok(Rreaddir {
-            data: Data(cursor.into_inner()),
-        })
-    }
-
-    fn fsync(&mut self, fsync: &Tfsync) -> io::Result<()> {
-        let file = self
-            .fids
-            .get(&fsync.fid)
-            .and_then(|fid| fid.file.as_ref())
-            .ok_or_else(ebadf)?;
-
-        if fsync.datasync == 0 {
-            file.sync_all()?;
-        } else {
-            file.sync_data()?;
-        }
-        Ok(())
-    }
-
-    fn lock(&mut self, _lock: &Tlock) -> io::Result<Rlock> {
-        // File locking is not supported.
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-    fn get_lock(&mut self, _get_lock: &Tgetlock) -> io::Result<Rgetlock> {
-        // File locking is not supported.
-        Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
-    }
-
-    fn link(&mut self, link: Tlink) -> io::Result<()> {
-        let target = self.fids.get(&link.fid).ok_or_else(ebadf)?;
-        let path = string_to_cstring(format!("self/fd/{}", target.path.as_raw_fd()))?;
-
-        let dir = self.fids.get(&link.dfid).ok_or_else(ebadf)?;
-        let name = string_to_cstring(link.name)?;
-
-        // Safe because this doesn't modify any memory and we check the return value.
-        syscall!(unsafe {
-            libc::linkat(
-                self.proc.as_raw_fd(),
-                path.as_ptr(),
-                dir.path.as_raw_fd(),
-                name.as_ptr(),
-                libc::AT_SYMLINK_FOLLOW,
-            )
-        })?;
-        Ok(())
-    }
-
-    fn mkdir(&mut self, mkdir: Tmkdir) -> io::Result<Rmkdir> {
-        let fid = self.fids.get(&mkdir.dfid).ok_or_else(ebadf)?;
-        let name = string_to_cstring(mkdir.name)?;
-
-        // Safe because this doesn't modify any memory and we check the return value.
-        syscall!(unsafe { libc::mkdirat(fid.path.as_raw_fd(), name.as_ptr(), mkdir.mode) })?;
-        Ok(Rmkdir {
-            qid: statat(&fid.path, &name, 0).map(Qid::from)?,
-        })
-    }
-
-    fn rename_at(&mut self, rename_at: Trenameat) -> io::Result<()> {
-        let olddir = self.fids.get(&rename_at.olddirfid).ok_or_else(ebadf)?;
-        let oldname = string_to_cstring(rename_at.oldname)?;
-
-        let newdir = self.fids.get(&rename_at.newdirfid).ok_or_else(ebadf)?;
-        let newname = string_to_cstring(rename_at.newname)?;
-
-        // Safe because this doesn't modify any memory and we check the return value.
-        syscall!(unsafe {
-            libc::renameat(
-                olddir.path.as_raw_fd(),
-                oldname.as_ptr(),
-                newdir.path.as_raw_fd(),
-                newname.as_ptr(),
-            )
-        })?;
-
-        Ok(())
-    }
-
-    fn unlink_at(&mut self, unlink_at: Tunlinkat) -> io::Result<()> {
-        let dir = self.fids.get(&unlink_at.dirfd).ok_or_else(ebadf)?;
-        let name = string_to_cstring(unlink_at.name)?;
-
-        syscall!(unsafe {
-            libc::unlinkat(
-                dir.path.as_raw_fd(),
-                name.as_ptr(),
-                unlink_at.flags as libc::c_int,
-            )
-        })?;
-
-        Ok(())
-    }
-}
-
-#[cfg(test)]
-mod tests;
diff --git a/src/server/tests.rs b/src/server/tests.rs
deleted file mode 100644
index ee122dd..0000000
--- a/src/server/tests.rs
+++ /dev/null
@@ -1,1147 +0,0 @@
-// Copyright 2019 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use super::*;
-
-use std::borrow::Cow;
-use std::collections::{HashSet, VecDeque};
-use std::env;
-use std::ffi::{CString, OsString};
-use std::fs::{self, File};
-use std::io::{self, Cursor};
-use std::mem;
-use std::ops::Deref;
-use std::os::unix::ffi::OsStringExt;
-use std::os::unix::fs::MetadataExt;
-use std::path::{Component, Path, PathBuf};
-use std::u32;
-
-// Used to indicate that there is no fid associated with this message.
-const P9_NOFID: u32 = u32::MAX;
-
-// The fid associated with the root directory of the server.
-const ROOT_FID: u32 = 1;
-
-// How big we want the default buffer to be when running tests.
-const DEFAULT_BUFFER_SIZE: u32 = 4096;
-
-// Joins `path` to `buf`.  If `path` is '..', removes the last component from `buf`
-// only if `buf` != `root` but does nothing if `buf` == `root`.  Pushes `path` onto
-// `buf` if it is a normal path component.
-//
-// Returns an error if `path` is absolute, has more than one component, or contains
-// a '.' component.
-fn join_path<P: AsRef<Path>, R: AsRef<Path>>(
-    mut buf: PathBuf,
-    path: P,
-    root: R,
-) -> io::Result<PathBuf> {
-    let path = path.as_ref();
-    let root = root.as_ref();
-    debug_assert!(buf.starts_with(root));
-
-    if path.components().count() > 1 {
-        return Err(io::Error::from_raw_os_error(libc::EINVAL));
-    }
-
-    for component in path.components() {
-        match component {
-            // Prefix should only appear on windows systems.
-            Component::Prefix(_) => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
-            // Absolute paths are not allowed.
-            Component::RootDir => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
-            // '.' elements are not allowed.
-            Component::CurDir => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
-            Component::ParentDir => {
-                // We only remove the parent path if we are not already at the root of the
-                // file system.
-                if buf != root {
-                    buf.pop();
-                }
-            }
-            Component::Normal(element) => buf.push(element),
-        }
-    }
-
-    Ok(buf)
-}
-
-// Automatically deletes the path it contains when it goes out of scope.
-struct ScopedPath<P: AsRef<Path>>(P);
-
-impl<P: AsRef<Path>> AsRef<Path> for ScopedPath<P> {
-    fn as_ref(&self) -> &Path {
-        self.0.as_ref()
-    }
-}
-
-impl<P: AsRef<Path>> Deref for ScopedPath<P> {
-    type Target = Path;
-
-    fn deref(&self) -> &Self::Target {
-        self.0.as_ref()
-    }
-}
-
-impl<P: AsRef<Path>> Drop for ScopedPath<P> {
-    fn drop(&mut self) {
-        if let Err(e) = fs::remove_dir_all(&**self) {
-            println!("Failed to remove {}: {}", self.display(), e);
-        }
-    }
-}
-
-enum DirEntry<'a> {
-    File {
-        name: &'a str,
-        content: &'a [u8],
-    },
-    Directory {
-        name: &'a str,
-        entries: &'a [DirEntry<'a>],
-    },
-}
-
-impl<'a> DirEntry<'a> {
-    // Creates `self` in the path given by `dir`.
-    fn create(&self, dir: &mut Cow<Path>) {
-        match *self {
-            DirEntry::File { name, content } => {
-                let mut f = File::create(dir.join(name)).expect("failed to create file");
-                f.write_all(content).expect("failed to write file content");
-            }
-            DirEntry::Directory { name, entries } => {
-                dir.to_mut().push(name);
-
-                fs::create_dir_all(&**dir).expect("failed to create directory");
-                for e in entries {
-                    e.create(dir);
-                }
-
-                assert!(dir.to_mut().pop());
-            }
-        }
-    }
-}
-
-// Creates a file with `name` in `dir` and fills it with random
-// content.
-fn create_local_file<P: AsRef<Path>>(dir: P, name: &str) -> Vec<u8> {
-    let mut content = Vec::new();
-    File::open("/dev/urandom")
-        .and_then(|f| f.take(200).read_to_end(&mut content))
-        .expect("failed to read from /dev/urandom");
-
-    let f = DirEntry::File {
-        name,
-        content: &content,
-    };
-    f.create(&mut Cow::from(dir.as_ref()));
-
-    content
-}
-
-fn check_qid(qid: &Qid, md: &fs::Metadata) {
-    let ty = if md.is_dir() {
-        P9_QTDIR
-    } else if md.is_file() {
-        P9_QTFILE
-    } else if md.file_type().is_symlink() {
-        P9_QTSYMLINK
-    } else {
-        panic!("unknown file type: {:?}", md.file_type());
-    };
-    assert_eq!(qid.ty, ty);
-    assert_eq!(qid.version, md.mtime() as u32);
-    assert_eq!(qid.path, md.ino());
-}
-
-fn check_attr(server: &mut Server, fid: u32, md: &fs::Metadata) {
-    let tgetattr = Tgetattr {
-        fid,
-        request_mask: P9_GETATTR_BASIC,
-    };
-
-    let rgetattr = server.get_attr(&tgetattr).expect("failed to call get_attr");
-
-    let ty = if md.is_dir() {
-        P9_QTDIR
-    } else if md.is_file() {
-        P9_QTFILE
-    } else if md.file_type().is_symlink() {
-        P9_QTSYMLINK
-    } else {
-        panic!("unknown file type: {:?}", md.file_type());
-    };
-    assert_eq!(rgetattr.valid, P9_GETATTR_BASIC);
-    assert_eq!(rgetattr.qid.ty, ty);
-    assert_eq!(rgetattr.qid.version, md.mtime() as u32);
-    assert_eq!(rgetattr.qid.path, md.ino());
-    assert_eq!(rgetattr.mode, md.mode());
-    assert_eq!(rgetattr.uid, md.uid());
-    assert_eq!(rgetattr.gid, md.gid());
-    assert_eq!(rgetattr.nlink, md.nlink());
-    assert_eq!(rgetattr.rdev, md.rdev());
-    assert_eq!(rgetattr.size, md.size());
-    assert_eq!(rgetattr.atime_sec, md.atime() as u64);
-    assert_eq!(rgetattr.atime_nsec, md.atime_nsec() as u64);
-    assert_eq!(rgetattr.mtime_sec, md.mtime() as u64);
-    assert_eq!(rgetattr.mtime_nsec, md.mtime_nsec() as u64);
-    assert_eq!(rgetattr.ctime_sec, md.ctime() as u64);
-    assert_eq!(rgetattr.ctime_nsec, md.ctime_nsec() as u64);
-    assert_eq!(rgetattr.btime_sec, 0);
-    assert_eq!(rgetattr.btime_nsec, 0);
-    assert_eq!(rgetattr.gen, 0);
-    assert_eq!(rgetattr.data_version, 0);
-}
-
-fn check_content(server: &mut Server, content: &[u8], fid: u32) {
-    for offset in 0..content.len() {
-        let tread = Tread {
-            fid,
-            offset: offset as u64,
-            count: DEFAULT_BUFFER_SIZE,
-        };
-
-        let rread = server.read(&tread).expect("failed to read file");
-        assert_eq!(content[offset..], rread.data[..]);
-    }
-}
-
-fn walk<P: Into<PathBuf>>(
-    server: &mut Server,
-    start: P,
-    fid: u32,
-    newfid: u32,
-    names: Vec<String>,
-) {
-    let mut mds = Vec::with_capacity(names.len());
-    let mut buf = start.into();
-    for name in &names {
-        buf.push(name);
-        mds.push(
-            buf.symlink_metadata()
-                .expect("failed to get metadata for path"),
-        );
-    }
-
-    let twalk = Twalk {
-        fid,
-        newfid,
-        wnames: names,
-    };
-
-    let rwalk = server.walk(twalk).expect("failed to walk directoy");
-    assert_eq!(mds.len(), rwalk.wqids.len());
-    for (md, qid) in mds.iter().zip(rwalk.wqids.iter()) {
-        check_qid(qid, md);
-    }
-}
-
-fn open<P: Into<PathBuf>>(
-    server: &mut Server,
-    dir: P,
-    dir_fid: u32,
-    name: &str,
-    fid: u32,
-    flags: u32,
-) -> io::Result<Rlopen> {
-    let wnames = if name.is_empty() {
-        vec![]
-    } else {
-        vec![String::from(name)]
-    };
-    walk(server, dir, dir_fid, fid, wnames);
-
-    let tlopen = Tlopen { fid, flags };
-
-    server.lopen(&tlopen)
-}
-
-fn write<P: AsRef<Path>>(server: &mut Server, dir: P, name: &str, fid: u32, flags: u32) {
-    let file_path = dir.as_ref().join(name);
-    let file_len = if file_path.exists() {
-        fs::symlink_metadata(&file_path)
-            .expect("unable to get metadata for file")
-            .len() as usize
-    } else {
-        0usize
-    };
-    let mut new_content = Vec::new();
-    File::open("/dev/urandom")
-        .and_then(|f| f.take(200).read_to_end(&mut new_content))
-        .expect("failed to read from /dev/urandom");
-
-    let twrite = Twrite {
-        fid,
-        offset: 0,
-        data: Data(new_content),
-    };
-
-    let rwrite = server.write(&twrite).expect("failed to write file");
-    assert_eq!(rwrite.count, twrite.data.len() as u32);
-
-    let tfsync = Tfsync { fid, datasync: 0 };
-    server.fsync(&tfsync).expect("failed to sync file contents");
-
-    let actual_content = fs::read(file_path).expect("failed to read back content from file");
-
-    // If the file was opened append-only, then the content should have been
-    // written to the end even though the offset was 0.
-    let idx = if flags & P9_APPEND == 0 { 0 } else { file_len };
-    assert_eq!(actual_content[idx..], twrite.data[..]);
-}
-
-fn create<P: Into<PathBuf>>(
-    server: &mut Server,
-    dir: P,
-    dir_fid: u32,
-    fid: u32,
-    name: &str,
-    flags: u32,
-    mode: u32,
-) -> io::Result<Rlcreate> {
-    // The `fid` in the lcreate call initially points to the directory
-    // but is supposed to point to the newly created file after the call
-    // completes.  Duplicate the fid so that we don't end up consuming the
-    // directory fid.
-    walk(server, dir, dir_fid, fid, Vec::new());
-
-    let tlcreate = Tlcreate {
-        fid,
-        name: String::from(name),
-        flags,
-        mode,
-        gid: 0,
-    };
-
-    server.lcreate(tlcreate)
-}
-
-struct Readdir<'a> {
-    server: &'a mut Server,
-    fid: u32,
-    offset: u64,
-    cursor: Cursor<Vec<u8>>,
-}
-
-impl<'a> Iterator for Readdir<'a> {
-    type Item = Dirent;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.cursor.position() >= self.cursor.get_ref().len() as u64 {
-            let treaddir = Treaddir {
-                fid: self.fid,
-                offset: self.offset,
-                count: DEFAULT_BUFFER_SIZE,
-            };
-
-            let Rreaddir { data } = self
-                .server
-                .readdir(&treaddir)
-                .expect("failed to read directory");
-            if data.is_empty() {
-                // No more entries.
-                return None;
-            }
-
-            mem::drop(mem::replace(&mut self.cursor, Cursor::new(data.0)));
-        }
-
-        let dirent: Dirent = WireFormat::decode(&mut self.cursor).expect("failed to decode dirent");
-        self.offset = dirent.offset;
-
-        Some(dirent)
-    }
-}
-
-fn readdir(server: &mut Server, fid: u32) -> Readdir {
-    Readdir {
-        server,
-        fid,
-        offset: 0,
-        cursor: Cursor::new(Vec::new()),
-    }
-}
-
-// Sets up the server to start handling messages.  Creates a new temporary
-// directory to act as the server root and sends an initial Tattach message.
-// At the end of setup, fid 1 points to the root of the server.
-fn setup<P: AsRef<Path>>(name: P) -> (ScopedPath<OsString>, Server) {
-    let mut test_dir = env::var_os("T")
-        .map(PathBuf::from)
-        .unwrap_or_else(env::temp_dir);
-    test_dir.push(name);
-
-    let mut os_str = OsString::from(test_dir);
-    os_str.push(".XXXXXX");
-
-    // Create a c string and release ownership.  This seems like the only way
-    // to get a *mut c_char.
-    let buf = CString::new(os_str.into_vec())
-        .expect("failed to create CString")
-        .into_raw();
-
-    // Safe because this will only modify the contents of `buf`.
-    let ret = unsafe { libc::mkdtemp(buf) };
-
-    // Take ownership of the buffer back before checking the result.  Safe because
-    // this was created by a call to into_raw() above and mkdtemp will not overwrite
-    // the trailing '\0'.
-    let buf = unsafe { CString::from_raw(buf) };
-
-    assert!(!ret.is_null());
-
-    let test_dir = ScopedPath(OsString::from_vec(buf.into_bytes()));
-
-    // Create a basic file system hierarchy.
-    let entries = [
-        DirEntry::Directory {
-            name: "subdir",
-            entries: &[
-                DirEntry::File {
-                    name: "b",
-                    content: b"hello, world!",
-                },
-                DirEntry::Directory {
-                    name: "nested",
-                    entries: &[DirEntry::File {
-                        name: "Огонь по готовности!",
-                        content: &[
-                            0xe9u8, 0xbeu8, 0x8du8, 0xe3u8, 0x81u8, 0x8cu8, 0xe6u8, 0x88u8, 0x91u8,
-                            0xe3u8, 0x81u8, 0x8cu8, 0xe6u8, 0x95u8, 0xb5u8, 0xe3u8, 0x82u8, 0x92u8,
-                            0xe5u8, 0x96u8, 0xb0u8, 0xe3u8, 0x82u8, 0x89u8, 0xe3u8, 0x81u8, 0x86u8,
-                            0x21u8,
-                        ],
-                    }],
-                },
-            ],
-        },
-        DirEntry::File {
-            name: "世界.txt",
-            content: &[
-                0xe3u8, 0x81u8, 0x93u8, 0xe3u8, 0x82u8, 0x93u8, 0xe3u8, 0x81u8, 0xabu8, 0xe3u8,
-                0x81u8, 0xa1u8, 0xe3u8, 0x81u8, 0xafu8,
-            ],
-        },
-    ];
-
-    for e in &entries {
-        e.create(&mut Cow::from(&*test_dir));
-    }
-
-    let md = test_dir
-        .symlink_metadata()
-        .expect("failed to get metadata for root dir");
-
-    let mut server = Server::new(&*test_dir, Default::default(), Default::default())
-        .expect("Failed to create server");
-
-    let tversion = Tversion {
-        msize: DEFAULT_BUFFER_SIZE,
-        version: String::from("9P2000.L"),
-    };
-
-    let rversion = server
-        .version(&tversion)
-        .expect("failed to get version from server");
-    assert_eq!(rversion.msize, DEFAULT_BUFFER_SIZE);
-    assert_eq!(rversion.version, "9P2000.L");
-
-    let tattach = Tattach {
-        fid: ROOT_FID,
-        afid: P9_NOFID,
-        uname: String::from("unittest"),
-        aname: String::from(""),
-        n_uname: 1000,
-    };
-
-    let rattach = server.attach(&tattach).expect("failed to attach to server");
-    check_qid(&rattach.qid, &md);
-
-    (test_dir, server)
-}
-
-#[test]
-fn path_joins() {
-    let root = PathBuf::from("/a/b/c");
-    let path = PathBuf::from("/a/b/c/d/e/f");
-
-    assert_eq!(
-        &join_path(path.clone(), "nested", &root).expect("normal"),
-        Path::new("/a/b/c/d/e/f/nested")
-    );
-
-    let p1 = join_path(path, "..", &root).expect("parent 1");
-    assert_eq!(&p1, Path::new("/a/b/c/d/e/"));
-
-    let p2 = join_path(p1, "..", &root).expect("parent 2");
-    assert_eq!(&p2, Path::new("/a/b/c/d/"));
-
-    let p3 = join_path(p2, "..", &root).expect("parent 3");
-    assert_eq!(&p3, Path::new("/a/b/c/"));
-
-    let p4 = join_path(p3, "..", &root).expect("parent of root");
-    assert_eq!(&p4, Path::new("/a/b/c/"));
-}
-
-#[test]
-fn invalid_joins() {
-    let root = PathBuf::from("/a");
-    let path = PathBuf::from("/a/b");
-
-    join_path(path.clone(), ".", &root).expect_err("current directory");
-    join_path(path.clone(), "c/d/e", &root).expect_err("too many components");
-    join_path(path, "/c/d/e", &root).expect_err("absolute path");
-}
-
-#[test]
-fn clunk() {
-    let (_test_dir, mut server) = setup("clunk");
-
-    let tclunk = Tclunk { fid: ROOT_FID };
-    server.clunk(&tclunk).expect("failed to clunk root fid");
-}
-
-#[test]
-fn get_attr() {
-    let (test_dir, mut server) = setup("get_attr");
-
-    let md = test_dir
-        .symlink_metadata()
-        .expect("failed to get metadata for test dir");
-
-    check_attr(&mut server, ROOT_FID, &md);
-}
-
-#[test]
-fn tree_walk() {
-    let (test_dir, mut server) = setup("readdir");
-
-    let mut next_fid = ROOT_FID + 1;
-
-    let mut dirs = VecDeque::new();
-    dirs.push_back(test_dir.to_path_buf());
-
-    while let Some(dir) = dirs.pop_front() {
-        let dfid = next_fid;
-        next_fid += 1;
-
-        let wnames: Vec<String> = dir
-            .strip_prefix(&test_dir)
-            .expect("test directory is not prefix of subdir")
-            .components()
-            .map(|c| Path::new(&c).to_string_lossy().to_string())
-            .collect();
-        walk(&mut server, &*test_dir, ROOT_FID, dfid, wnames);
-
-        let md = dir.symlink_metadata().expect("failed to get metadata");
-
-        check_attr(&mut server, dfid, &md);
-
-        let fid = next_fid;
-        next_fid += 1;
-        open(&mut server, &dir, dfid, "", fid, P9_DIRECTORY).expect("Failed to open directory");
-        for dirent in readdir(&mut server, fid) {
-            if dirent.name == "." || dirent.name == ".." {
-                continue;
-            }
-
-            let entry_path = dir.join(&dirent.name);
-            assert!(
-                entry_path.exists(),
-                "directory entry \"{}\" does not exist",
-                entry_path.display()
-            );
-            let md = fs::symlink_metadata(&entry_path).expect("failed to get metadata for entry");
-
-            let ty = if md.is_dir() {
-                dirs.push_back(dir.join(dirent.name));
-                libc::DT_DIR
-            } else if md.is_file() {
-                libc::DT_REG
-            } else if md.file_type().is_symlink() {
-                libc::DT_LNK
-            } else {
-                panic!("unknown file type: {:?}", md.file_type());
-            };
-
-            assert_eq!(dirent.ty, ty);
-            check_qid(&dirent.qid, &md);
-        }
-
-        let tclunk = Tclunk { fid };
-        server.clunk(&tclunk).expect("failed to clunk fid");
-    }
-}
-
-#[test]
-fn create_existing_file() {
-    let (test_dir, mut server) = setup("create_existing");
-
-    let name = "existing";
-    create_local_file(&test_dir, name);
-
-    let fid = ROOT_FID + 1;
-    create(
-        &mut server,
-        &*test_dir,
-        ROOT_FID,
-        fid,
-        name,
-        P9_APPEND,
-        0o644,
-    )
-    .expect_err("successfully created existing file");
-}
-
-enum SetAttrKind {
-    File,
-    Directory,
-}
-
-fn set_attr_test<F>(kind: SetAttrKind, set_fields: F) -> io::Result<fs::Metadata>
-where
-    F: FnOnce(&mut Tsetattr),
-{
-    let (test_dir, mut server) = setup("set_attr");
-
-    let name = "existing";
-    match kind {
-        SetAttrKind::File => {
-            create_local_file(&test_dir, name);
-        }
-        SetAttrKind::Directory => {
-            let tmkdir = Tmkdir {
-                dfid: ROOT_FID,
-                name: String::from(name),
-                mode: 0o755,
-                gid: 0,
-            };
-
-            let rmkdir = server.mkdir(tmkdir).expect("failed to create directory");
-            let md = fs::symlink_metadata(test_dir.join(name))
-                .expect("failed to get metadata for directory");
-
-            assert!(md.is_dir());
-            check_qid(&rmkdir.qid, &md);
-        }
-    };
-
-    let fid = ROOT_FID + 1;
-    walk(
-        &mut server,
-        &*test_dir,
-        ROOT_FID,
-        fid,
-        vec![String::from(name)],
-    );
-
-    let mut tsetattr = Tsetattr {
-        fid,
-        valid: 0,
-        mode: 0,
-        uid: 0,
-        gid: 0,
-        size: 0,
-        atime_sec: 0,
-        atime_nsec: 0,
-        mtime_sec: 0,
-        mtime_nsec: 0,
-    };
-
-    set_fields(&mut tsetattr);
-    server.set_attr(&tsetattr)?;
-
-    fs::symlink_metadata(test_dir.join(name))
-}
-
-#[test]
-fn set_len() {
-    let len = 661;
-    let md = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_SIZE;
-        tsetattr.size = len;
-    })
-    .expect("failed to run set length of file");
-
-    assert_eq!(md.size(), len);
-}
-
-#[test]
-fn set_file_mode() {
-    let mode = 0o640;
-    let err = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_MODE;
-        tsetattr.mode = mode;
-    })
-    .expect_err("successfully set mode");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_file_uid() {
-    let uid = 294;
-    let err = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_UID;
-        tsetattr.uid = uid;
-    })
-    .expect_err("successfully set uid");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_file_gid() {
-    let gid = 9024;
-    let err = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_GID;
-        tsetattr.gid = gid;
-    })
-    .expect_err("successfully set gid");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_file_mtime() {
-    let (secs, nanos) = (1245247825, 524617);
-    let md = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_MTIME | P9_SETATTR_MTIME_SET;
-        tsetattr.mtime_sec = secs;
-        tsetattr.mtime_nsec = nanos;
-    })
-    .expect("failed to set mtime");
-
-    assert_eq!(md.mtime() as u64, secs);
-    assert_eq!(md.mtime_nsec() as u64, nanos);
-}
-
-#[test]
-fn set_file_atime() {
-    let (secs, nanos) = (9247605, 4016);
-    let md = set_attr_test(SetAttrKind::File, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_ATIME | P9_SETATTR_ATIME_SET;
-        tsetattr.atime_sec = secs;
-        tsetattr.atime_nsec = nanos;
-    })
-    .expect("failed to set atime");
-
-    assert_eq!(md.atime() as u64, secs);
-    assert_eq!(md.atime_nsec() as u64, nanos);
-}
-
-#[test]
-fn set_dir_mode() {
-    let mode = 0o640;
-    let err = set_attr_test(SetAttrKind::Directory, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_MODE;
-        tsetattr.mode = mode;
-    })
-    .expect_err("successfully set mode");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_dir_uid() {
-    let uid = 294;
-    let err = set_attr_test(SetAttrKind::Directory, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_UID;
-        tsetattr.uid = uid;
-    })
-    .expect_err("successfully set uid");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_dir_gid() {
-    let gid = 9024;
-    let err = set_attr_test(SetAttrKind::Directory, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_GID;
-        tsetattr.gid = gid;
-    })
-    .expect_err("successfully set gid");
-
-    assert_eq!(err.kind(), io::ErrorKind::PermissionDenied);
-}
-
-#[test]
-fn set_dir_mtime() {
-    let (secs, nanos) = (1245247825, 524617);
-    let md = set_attr_test(SetAttrKind::Directory, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_MTIME | P9_SETATTR_MTIME_SET;
-        tsetattr.mtime_sec = secs;
-        tsetattr.mtime_nsec = nanos;
-    })
-    .expect("failed to set mtime");
-
-    assert_eq!(md.mtime() as u64, secs);
-    assert_eq!(md.mtime_nsec() as u64, nanos);
-}
-
-#[test]
-fn set_dir_atime() {
-    let (secs, nanos) = (9247605, 4016);
-    let md = set_attr_test(SetAttrKind::Directory, |tsetattr| {
-        tsetattr.valid = P9_SETATTR_ATIME | P9_SETATTR_ATIME_SET;
-        tsetattr.atime_sec = secs;
-        tsetattr.atime_nsec = nanos;
-    })
-    .expect("failed to set atime");
-
-    assert_eq!(md.atime() as u64, secs);
-    assert_eq!(md.atime_nsec() as u64, nanos);
-}
-
-#[test]
-fn huge_directory() {
-    let (test_dir, mut server) = setup("huge_directory");
-
-    let name = "newdir";
-    let newdir = test_dir.join(name);
-    fs::create_dir(&newdir).expect("failed to create directory");
-
-    let dfid = ROOT_FID + 1;
-    walk(
-        &mut server,
-        &*test_dir,
-        ROOT_FID,
-        dfid,
-        vec![String::from(name)],
-    );
-
-    // Create ~4K files in the directory and then attempt to read them all.
-    let mut filenames = HashSet::with_capacity(4096);
-    for i in 0..4096 {
-        let name = format!("file_{}", i);
-        create_local_file(&newdir, &name);
-        assert!(filenames.insert(name));
-    }
-
-    let fid = dfid + 1;
-    open(&mut server, &newdir, dfid, "", fid, P9_DIRECTORY).expect("Failed to open directory");
-    for f in readdir(&mut server, fid) {
-        let path = newdir.join(&f.name);
-
-        let md = fs::symlink_metadata(path).expect("failed to get metadata for path");
-        check_qid(&f.qid, &md);
-
-        if f.name == "." || f.name == ".." {
-            assert_eq!(f.ty, libc::DT_DIR);
-        } else {
-            assert_eq!(f.ty, libc::DT_REG);
-            assert!(filenames.remove(&f.name));
-        }
-    }
-
-    assert!(filenames.is_empty());
-}
-
-#[test]
-fn mkdir() {
-    let (test_dir, mut server) = setup("mkdir");
-
-    let name = "conan";
-    let tmkdir = Tmkdir {
-        dfid: ROOT_FID,
-        name: String::from(name),
-        mode: 0o755,
-        gid: 0,
-    };
-
-    let rmkdir = server.mkdir(tmkdir).expect("failed to create directory");
-    let md =
-        fs::symlink_metadata(test_dir.join(name)).expect("failed to get metadata for directory");
-
-    assert!(md.is_dir());
-    check_qid(&rmkdir.qid, &md);
-}
-
-#[test]
-fn unlink_all() {
-    let (test_dir, mut server) = setup("readdir");
-
-    let mut next_fid = ROOT_FID + 1;
-
-    let mut dirs = VecDeque::new();
-    dirs.push_back((ROOT_FID, test_dir.to_path_buf()));
-
-    // First iterate over the whole directory.
-    let mut unlinks = VecDeque::new();
-    while let Some((dfid, dir)) = dirs.pop_front() {
-        let mut names = VecDeque::new();
-        for entry in fs::read_dir(dir).expect("failed to read directory") {
-            let entry = entry.expect("unable to iterate over directory");
-            let ft = entry
-                .file_type()
-                .expect("failed to get file type for entry");
-            if ft.is_dir() {
-                let fid = next_fid;
-                next_fid += 1;
-
-                let wnames: Vec<String> = entry
-                    .path()
-                    .strip_prefix(&test_dir)
-                    .expect("test directory is not prefix of subdir")
-                    .components()
-                    .map(|c| Path::new(&c).to_string_lossy().to_string())
-                    .collect();
-                walk(&mut server, &*test_dir, ROOT_FID, fid, wnames);
-                dirs.push_back((fid, entry.path()));
-            }
-
-            names.push_back((
-                entry
-                    .file_name()
-                    .into_string()
-                    .expect("failed to convert entry name to string"),
-                if ft.is_dir() {
-                    libc::AT_REMOVEDIR as u32
-                } else {
-                    0
-                },
-            ));
-        }
-
-        unlinks.push_back((dfid, names));
-    }
-
-    // Now remove everything in reverse order.
-    while let Some((dfid, names)) = unlinks.pop_back() {
-        for (name, flags) in names {
-            let tunlinkat = Tunlinkat {
-                dirfd: dfid,
-                name,
-                flags,
-            };
-
-            server.unlink_at(tunlinkat).expect("failed to unlink path");
-        }
-    }
-}
-
-#[test]
-fn rename_at() {
-    let (test_dir, mut server) = setup("rename");
-
-    let name = "oldfile";
-    let content = create_local_file(&test_dir, name);
-
-    let newname = "newfile";
-    let trename = Trenameat {
-        olddirfid: ROOT_FID,
-        oldname: String::from(name),
-        newdirfid: ROOT_FID,
-        newname: String::from(newname),
-    };
-
-    server.rename_at(trename).expect("failed to rename file");
-
-    assert!(!test_dir.join(name).exists());
-
-    let mut newcontent = Vec::with_capacity(content.len());
-    let size = File::open(test_dir.join(newname))
-        .expect("failed to open file")
-        .read_to_end(&mut newcontent)
-        .expect("failed to read new file content");
-    assert_eq!(size, content.len());
-    assert_eq!(newcontent, content);
-}
-
-macro_rules! open_test {
-    ($name:ident, $flags:expr) => {
-        #[test]
-        fn $name() {
-            let (test_dir, mut server) = setup("open");
-
-            let fid = ROOT_FID + 1;
-            let name = "test.txt";
-            let content = create_local_file(&test_dir, name);
-
-            let rlopen = open(&mut server, &*test_dir, ROOT_FID, name, fid, $flags as u32)
-                .expect("failed to open file");
-
-            let md =
-                fs::symlink_metadata(test_dir.join(name)).expect("failed to get metadata for file");
-            check_qid(&rlopen.qid, &md);
-            assert_eq!(rlopen.iounit, md.blksize() as u32);
-
-            check_attr(&mut server, fid, &md);
-
-            // Check that the file has the proper contents as long as we didn't
-            // truncate it first.
-            if $flags & P9_TRUNC == 0 && $flags & P9_WRONLY == 0 {
-                check_content(&mut server, &content, fid);
-            }
-
-            // Check that we can write to the file.
-            if $flags & P9_RDWR != 0 || $flags & P9_WRONLY != 0 {
-                write(&mut server, &test_dir, name, fid, $flags);
-            }
-
-            let tclunk = Tclunk { fid };
-            server.clunk(&tclunk).expect("Unable to clunk file");
-        }
-    };
-    ($name:ident, $flags:expr, $expected_err:expr) => {
-        #[test]
-        fn $name() {
-            let (test_dir, mut server) = setup("open_fail");
-
-            let fid = ROOT_FID + 1;
-            let name = "test.txt";
-            create_local_file(&test_dir, name);
-
-            let err = open(&mut server, &*test_dir, ROOT_FID, name, fid, $flags as u32)
-                .expect_err("successfully opened file");
-            assert_eq!(err.kind(), $expected_err);
-
-            let tclunk = Tclunk { fid };
-            server.clunk(&tclunk).expect("Unable to clunk file");
-        }
-    };
-}
-
-open_test!(read_only_file_open, P9_RDONLY);
-open_test!(read_write_file_open, P9_RDWR);
-open_test!(write_only_file_open, P9_WRONLY);
-
-open_test!(create_read_only_file_open, P9_CREATE | P9_RDONLY);
-open_test!(create_read_write_file_open, P9_CREATE | P9_RDWR);
-open_test!(create_write_only_file_open, P9_CREATE | P9_WRONLY);
-
-open_test!(append_read_only_file_open, P9_APPEND | P9_RDONLY);
-open_test!(append_read_write_file_open, P9_APPEND | P9_RDWR);
-open_test!(append_write_only_file_open, P9_APPEND | P9_WRONLY);
-
-open_test!(trunc_read_only_file_open, P9_TRUNC | P9_RDONLY);
-open_test!(trunc_read_write_file_open, P9_TRUNC | P9_RDWR);
-open_test!(trunc_write_only_file_open, P9_TRUNC | P9_WRONLY);
-
-open_test!(
-    create_append_read_only_file_open,
-    P9_CREATE | P9_APPEND | P9_RDONLY
-);
-open_test!(
-    create_append_read_write_file_open,
-    P9_CREATE | P9_APPEND | P9_RDWR
-);
-open_test!(
-    create_append_wronly_file_open,
-    P9_CREATE | P9_APPEND | P9_WRONLY
-);
-
-open_test!(
-    create_trunc_read_only_file_open,
-    P9_CREATE | P9_TRUNC | P9_RDONLY
-);
-open_test!(
-    create_trunc_read_write_file_open,
-    P9_CREATE | P9_TRUNC | P9_RDWR
-);
-open_test!(
-    create_trunc_wronly_file_open,
-    P9_CREATE | P9_TRUNC | P9_WRONLY
-);
-
-open_test!(
-    append_trunc_read_only_file_open,
-    P9_APPEND | P9_TRUNC | P9_RDONLY
-);
-open_test!(
-    append_trunc_read_write_file_open,
-    P9_APPEND | P9_TRUNC | P9_RDWR
-);
-open_test!(
-    append_trunc_wronly_file_open,
-    P9_APPEND | P9_TRUNC | P9_WRONLY
-);
-
-open_test!(
-    create_append_trunc_read_only_file_open,
-    P9_CREATE | P9_APPEND | P9_TRUNC | P9_RDONLY
-);
-open_test!(
-    create_append_trunc_read_write_file_open,
-    P9_CREATE | P9_APPEND | P9_TRUNC | P9_RDWR
-);
-open_test!(
-    create_append_trunc_wronly_file_open,
-    P9_CREATE | P9_APPEND | P9_TRUNC | P9_WRONLY
-);
-
-open_test!(
-    create_excl_read_only_file_open,
-    P9_CREATE | P9_EXCL | P9_RDONLY,
-    io::ErrorKind::AlreadyExists
-);
-open_test!(
-    create_excl_read_write_file_open,
-    P9_CREATE | P9_EXCL | P9_RDWR,
-    io::ErrorKind::AlreadyExists
-);
-open_test!(
-    create_excl_wronly_file_open,
-    P9_CREATE | P9_EXCL | P9_WRONLY,
-    io::ErrorKind::AlreadyExists
-);
-
-macro_rules! create_test {
-    ($name:ident, $flags:expr, $mode:expr) => {
-        #[test]
-        fn $name() {
-            let (test_dir, mut server) = setup("create");
-
-            let name = "foo.txt";
-            let fid = ROOT_FID + 1;
-            let rlcreate = create(&mut server, &*test_dir, ROOT_FID, fid, name, $flags, $mode)
-                .expect("failed to create file");
-
-            let md =
-                fs::symlink_metadata(test_dir.join(name)).expect("failed to get metadata for file");
-            assert_eq!(rlcreate.iounit, md.blksize() as u32);
-            check_qid(&rlcreate.qid, &md);
-            check_attr(&mut server, fid, &md);
-
-            // Check that we can write to the file.
-            if $flags & P9_RDWR != 0 || $flags & P9_WRONLY != 0 {
-                write(&mut server, &test_dir, name, fid, $flags);
-            }
-
-            let tclunk = Tclunk { fid };
-            server.clunk(&tclunk).expect("Unable to clunk file");
-        }
-    };
-    ($name:ident, $flags:expr, $mode:expr, $expected_err:expr) => {
-        #[test]
-        fn $name() {
-            let (test_dir, mut server) = setup("create_fail");
-
-            let name = "foo.txt";
-            // The `fid` in the lcreate call initially points to the directory
-            // but is supposed to point to the newly created file after the call
-            // completes.  Duplicate the fid so that we don't end up consuming the
-            // root fid.
-            let fid = ROOT_FID + 1;
-            let err = create(&mut server, &*test_dir, ROOT_FID, fid, name, $flags, $mode)
-                .expect_err("successfully created file");
-            assert_eq!(err.kind(), $expected_err);
-        }
-    };
-}
-
-create_test!(read_only_file_create, P9_RDONLY, 0o600u32);
-create_test!(read_write_file_create, P9_RDWR, 0o600u32);
-create_test!(write_only_file_create, P9_WRONLY, 0o600u32);
-
-create_test!(
-    append_read_only_file_create,
-    P9_APPEND | P9_RDONLY,
-    0o600u32
-);
-create_test!(append_read_write_file_create, P9_APPEND | P9_RDWR, 0o600u32);
-create_test!(append_wronly_file_create, P9_APPEND | P9_WRONLY, 0o600u32);
diff --git a/wire_format_derive/Android.bp b/wire_format_derive/Android.bp
deleted file mode 100644
index b5908db..0000000
--- a/wire_format_derive/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-// This file is generated by cargo2android.py --run --device --tests --dependencies --patch=patches/Android.bp.patch.
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_vm_tools_p9_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-BSD
-    default_applicable_licenses: ["external_vm_tools_p9_license"],
-}
-
-rust_proc_macro {
-    name: "libwire_format_derive",
-    crate_name: "wire_format_derive",
-    srcs: ["wire_format_derive.rs"],
-    edition: "2015",
-    rustlibs: [
-        "libproc_macro2",
-        "libquote",
-        "libsyn",
-    ],
-}
diff --git a/wire_format_derive/Cargo.toml b/wire_format_derive/Cargo.toml
deleted file mode 100644
index 52ab6a4..0000000
--- a/wire_format_derive/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "wire_format_derive"
-version = "0.1.0"
-authors = ["The Chromium OS Authors"]
-
-[dependencies]
-syn = "^1"
-quote = "^1"
-proc-macro2 = "^1"
-
-[lib]
-proc-macro = true
-path = "wire_format_derive.rs"
diff --git a/wire_format_derive/wire_format_derive.rs b/wire_format_derive/wire_format_derive.rs
deleted file mode 100644
index 290ffc5..0000000
--- a/wire_format_derive/wire_format_derive.rs
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//! Derives a 9P wire format encoding for a struct by recursively calling
-//! `WireFormat::encode` or `WireFormat::decode` on the fields of the struct.
-//! This is only intended to be used from within the `p9` crate.
-
-#![recursion_limit = "256"]
-
-extern crate proc_macro;
-extern crate proc_macro2;
-
-#[macro_use]
-extern crate quote;
-
-#[macro_use]
-extern crate syn;
-
-use proc_macro2::{Span, TokenStream};
-use syn::spanned::Spanned;
-use syn::{Data, DeriveInput, Fields, Ident};
-
-/// The function that derives the actual implementation.
-#[proc_macro_derive(P9WireFormat)]
-pub fn p9_wire_format(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    let input = parse_macro_input!(input as DeriveInput);
-    p9_wire_format_inner(input).into()
-}
-
-fn p9_wire_format_inner(input: DeriveInput) -> TokenStream {
-    if !input.generics.params.is_empty() {
-        return quote! {
-            compile_error!("derive(P9WireFormat) does not support generic parameters");
-        };
-    }
-
-    let container = input.ident;
-
-    let byte_size_impl = byte_size_sum(&input.data);
-    let encode_impl = encode_wire_format(&input.data);
-    let decode_impl = decode_wire_format(&input.data, &container);
-
-    let scope = format!("wire_format_{}", container).to_lowercase();
-    let scope = Ident::new(&scope, Span::call_site());
-    quote! {
-        mod #scope {
-            extern crate std;
-            use self::std::io;
-            use self::std::result::Result::Ok;
-
-            use super::#container;
-
-            use protocol::WireFormat;
-
-            impl WireFormat for #container {
-                fn byte_size(&self) -> u32 {
-                    #byte_size_impl
-                }
-
-                fn encode<W: io::Write>(&self, _writer: &mut W) -> io::Result<()> {
-                    #encode_impl
-                }
-
-                fn decode<R: io::Read>(_reader: &mut R) -> io::Result<Self> {
-                    #decode_impl
-                }
-            }
-        }
-    }
-}
-
-// Generate code that recursively calls byte_size on every field in the struct.
-fn byte_size_sum(data: &Data) -> TokenStream {
-    if let Data::Struct(ref data) = *data {
-        if let Fields::Named(ref fields) = data.fields {
-            let fields = fields.named.iter().map(|f| {
-                let field = &f.ident;
-                let span = field.span();
-                quote_spanned! {span=>
-                    WireFormat::byte_size(&self.#field)
-                }
-            });
-
-            quote! {
-                0 #(+ #fields)*
-            }
-        } else {
-            unimplemented!();
-        }
-    } else {
-        unimplemented!();
-    }
-}
-
-// Generate code that recursively calls encode on every field in the struct.
-fn encode_wire_format(data: &Data) -> TokenStream {
-    if let Data::Struct(ref data) = *data {
-        if let Fields::Named(ref fields) = data.fields {
-            let fields = fields.named.iter().map(|f| {
-                let field = &f.ident;
-                let span = field.span();
-                quote_spanned! {span=>
-                    WireFormat::encode(&self.#field, _writer)?;
-                }
-            });
-
-            quote! {
-                #(#fields)*
-
-                Ok(())
-            }
-        } else {
-            unimplemented!();
-        }
-    } else {
-        unimplemented!();
-    }
-}
-
-// Generate code that recursively calls decode on every field in the struct.
-fn decode_wire_format(data: &Data, container: &Ident) -> TokenStream {
-    if let Data::Struct(ref data) = *data {
-        if let Fields::Named(ref fields) = data.fields {
-            let values = fields.named.iter().map(|f| {
-                let field = &f.ident;
-                let span = field.span();
-                quote_spanned! {span=>
-                    let #field = WireFormat::decode(_reader)?;
-                }
-            });
-
-            let members = fields.named.iter().map(|f| {
-                let field = &f.ident;
-                quote! {
-                    #field: #field,
-                }
-            });
-
-            quote! {
-                #(#values)*
-
-                Ok(#container {
-                    #(#members)*
-                })
-            }
-        } else {
-            unimplemented!();
-        }
-    } else {
-        unimplemented!();
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn byte_size() {
-        let input: DeriveInput = parse_quote! {
-            struct Item {
-                ident: u32,
-                with_underscores: String,
-                other: u8,
-            }
-        };
-
-        let expected = quote! {
-            0
-                + WireFormat::byte_size(&self.ident)
-                + WireFormat::byte_size(&self.with_underscores)
-                + WireFormat::byte_size(&self.other)
-        };
-
-        assert_eq!(byte_size_sum(&input.data).to_string(), expected.to_string());
-    }
-
-    #[test]
-    fn encode() {
-        let input: DeriveInput = parse_quote! {
-            struct Item {
-                ident: u32,
-                with_underscores: String,
-                other: u8,
-            }
-        };
-
-        let expected = quote! {
-            WireFormat::encode(&self.ident, _writer)?;
-            WireFormat::encode(&self.with_underscores, _writer)?;
-            WireFormat::encode(&self.other, _writer)?;
-            Ok(())
-        };
-
-        assert_eq!(
-            encode_wire_format(&input.data).to_string(),
-            expected.to_string(),
-        );
-    }
-
-    #[test]
-    fn decode() {
-        let input: DeriveInput = parse_quote! {
-            struct Item {
-                ident: u32,
-                with_underscores: String,
-                other: u8,
-            }
-        };
-
-        let container = Ident::new("Item", Span::call_site());
-        let expected = quote! {
-            let ident = WireFormat::decode(_reader)?;
-            let with_underscores = WireFormat::decode(_reader)?;
-            let other = WireFormat::decode(_reader)?;
-            Ok(Item {
-                ident: ident,
-                with_underscores: with_underscores,
-                other: other,
-            })
-        };
-
-        assert_eq!(
-            decode_wire_format(&input.data, &container).to_string(),
-            expected.to_string(),
-        );
-    }
-
-    #[test]
-    fn end_to_end() {
-        let input: DeriveInput = parse_quote! {
-            struct Niijima_先輩 {
-                a: u8,
-                b: u16,
-                c: u32,
-                d: u64,
-                e: String,
-                f: Vec<String>,
-                g: Nested,
-            }
-        };
-
-        let expected = quote! {
-            mod wire_format_niijima_先輩 {
-                extern crate std;
-                use self::std::io;
-                use self::std::result::Result::Ok;
-
-                use super::Niijima_先輩;
-
-                use protocol::WireFormat;
-
-                impl WireFormat for Niijima_先輩 {
-                    fn byte_size(&self) -> u32 {
-                        0
-                        + WireFormat::byte_size(&self.a)
-                        + WireFormat::byte_size(&self.b)
-                        + WireFormat::byte_size(&self.c)
-                        + WireFormat::byte_size(&self.d)
-                        + WireFormat::byte_size(&self.e)
-                        + WireFormat::byte_size(&self.f)
-                        + WireFormat::byte_size(&self.g)
-                    }
-
-                    fn encode<W: io::Write>(&self, _writer: &mut W) -> io::Result<()> {
-                        WireFormat::encode(&self.a, _writer)?;
-                        WireFormat::encode(&self.b, _writer)?;
-                        WireFormat::encode(&self.c, _writer)?;
-                        WireFormat::encode(&self.d, _writer)?;
-                        WireFormat::encode(&self.e, _writer)?;
-                        WireFormat::encode(&self.f, _writer)?;
-                        WireFormat::encode(&self.g, _writer)?;
-                        Ok(())
-                    }
-                    fn decode<R: io::Read>(_reader: &mut R) -> io::Result<Self> {
-                        let a = WireFormat::decode(_reader)?;
-                        let b = WireFormat::decode(_reader)?;
-                        let c = WireFormat::decode(_reader)?;
-                        let d = WireFormat::decode(_reader)?;
-                        let e = WireFormat::decode(_reader)?;
-                        let f = WireFormat::decode(_reader)?;
-                        let g = WireFormat::decode(_reader)?;
-                        Ok(Niijima_先輩 {
-                            a: a,
-                            b: b,
-                            c: c,
-                            d: d,
-                            e: e,
-                            f: f,
-                            g: g,
-                        })
-                    }
-                }
-            }
-        };
-
-        assert_eq!(
-            p9_wire_format_inner(input).to_string(),
-            expected.to_string(),
-        );
-    }
-}