mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-12-25 04:14:06 +00:00
p9: protocol: Add message definitions
Add definitions for all the messages we expect to send and receive over the wire. BUG=chromium:703939 TEST=none Change-Id: I6b48f3e2eb9779fca57f8b71120b7bb1e8ab4ab9 Signed-off-by: Chirantan Ekbote <chirantan@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1013201 Reviewed-by: Stephen Barber <smbarber@chromium.org>
This commit is contained in:
parent
800fcb060f
commit
9b81eb57f3
2 changed files with 842 additions and 0 deletions
840
p9/src/protocol/messages.rs
Normal file
840
p9/src/protocol/messages.rs
Normal file
|
@ -0,0 +1,840 @@
|
|||
// 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 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,
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
// 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};
|
||||
|
|
Loading…
Reference in a new issue