| // 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: tag, msg: 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: tag, msg: 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, |
| } |