1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::io::{self, ErrorKind, Read, Write}; 6 use std::mem; 7 use std::string::String; 8 use std::vec::Vec; 9 10 use crate::protocol::wire_format::{Data, WireFormat}; 11 12 // Message type constants. Taken from "include/net/9p/9p.h" in the linux kernel 13 // tree. The protocol specifies each R* message to be the corresponding T* 14 // message plus one. 15 const TLERROR: u8 = 6; 16 const RLERROR: u8 = TLERROR + 1; 17 const TSTATFS: u8 = 8; 18 const RSTATFS: u8 = TSTATFS + 1; 19 const TLOPEN: u8 = 12; 20 const RLOPEN: u8 = TLOPEN + 1; 21 const TLCREATE: u8 = 14; 22 const RLCREATE: u8 = TLCREATE + 1; 23 const TSYMLINK: u8 = 16; 24 const RSYMLINK: u8 = TSYMLINK + 1; 25 const TMKNOD: u8 = 18; 26 const RMKNOD: u8 = TMKNOD + 1; 27 const TRENAME: u8 = 20; 28 const RRENAME: u8 = TRENAME + 1; 29 const TREADLINK: u8 = 22; 30 const RREADLINK: u8 = TREADLINK + 1; 31 const TGETATTR: u8 = 24; 32 const RGETATTR: u8 = TGETATTR + 1; 33 const TSETATTR: u8 = 26; 34 const RSETATTR: u8 = TSETATTR + 1; 35 const TXATTRWALK: u8 = 30; 36 const RXATTRWALK: u8 = TXATTRWALK + 1; 37 const TXATTRCREATE: u8 = 32; 38 const RXATTRCREATE: u8 = TXATTRCREATE + 1; 39 const TREADDIR: u8 = 40; 40 const RREADDIR: u8 = TREADDIR + 1; 41 const TFSYNC: u8 = 50; 42 const RFSYNC: u8 = TFSYNC + 1; 43 const TLOCK: u8 = 52; 44 const RLOCK: u8 = TLOCK + 1; 45 const TGETLOCK: u8 = 54; 46 const RGETLOCK: u8 = TGETLOCK + 1; 47 const TLINK: u8 = 70; 48 const RLINK: u8 = TLINK + 1; 49 const TMKDIR: u8 = 72; 50 const RMKDIR: u8 = TMKDIR + 1; 51 const TRENAMEAT: u8 = 74; 52 const RRENAMEAT: u8 = TRENAMEAT + 1; 53 const TUNLINKAT: u8 = 76; 54 const RUNLINKAT: u8 = TUNLINKAT + 1; 55 const TVERSION: u8 = 100; 56 const RVERSION: u8 = TVERSION + 1; 57 const TAUTH: u8 = 102; 58 const RAUTH: u8 = TAUTH + 1; 59 const TATTACH: u8 = 104; 60 const RATTACH: u8 = TATTACH + 1; 61 const _TERROR: u8 = 106; 62 const _RERROR: u8 = _TERROR + 1; 63 const TFLUSH: u8 = 108; 64 const RFLUSH: u8 = TFLUSH + 1; 65 const TWALK: u8 = 110; 66 const RWALK: u8 = TWALK + 1; 67 const _TOPEN: u8 = 112; 68 const _ROPEN: u8 = _TOPEN + 1; 69 const _TCREATE: u8 = 114; 70 const _RCREATE: u8 = _TCREATE + 1; 71 const TREAD: u8 = 116; 72 const RREAD: u8 = TREAD + 1; 73 const TWRITE: u8 = 118; 74 const RWRITE: u8 = TWRITE + 1; 75 const TCLUNK: u8 = 120; 76 const RCLUNK: u8 = TCLUNK + 1; 77 const TREMOVE: u8 = 122; 78 const RREMOVE: u8 = TREMOVE + 1; 79 const _TSTAT: u8 = 124; 80 const _RSTAT: u8 = _TSTAT + 1; 81 const _TWSTAT: u8 = 126; 82 const _RWSTAT: u8 = _TWSTAT + 1; 83 84 /// A message sent from a 9P client to a 9P server. 85 #[derive(Debug)] 86 pub enum Tmessage { 87 Version(Tversion), 88 Flush(Tflush), 89 Walk(Twalk), 90 Read(Tread), 91 Write(Twrite), 92 Clunk(Tclunk), 93 Remove(Tremove), 94 Attach(Tattach), 95 Auth(Tauth), 96 Statfs(Tstatfs), 97 Lopen(Tlopen), 98 Lcreate(Tlcreate), 99 Symlink(Tsymlink), 100 Mknod(Tmknod), 101 Rename(Trename), 102 Readlink(Treadlink), 103 GetAttr(Tgetattr), 104 SetAttr(Tsetattr), 105 XattrWalk(Txattrwalk), 106 XattrCreate(Txattrcreate), 107 Readdir(Treaddir), 108 Fsync(Tfsync), 109 Lock(Tlock), 110 GetLock(Tgetlock), 111 Link(Tlink), 112 Mkdir(Tmkdir), 113 RenameAt(Trenameat), 114 UnlinkAt(Tunlinkat), 115 } 116 117 #[derive(Debug)] 118 pub struct Tframe { 119 pub tag: u16, 120 pub msg: Tmessage, 121 } 122 123 impl WireFormat for Tframe { byte_size(&self) -> u32124 fn byte_size(&self) -> u32 { 125 let msg_size = match self.msg { 126 Tmessage::Version(ref version) => version.byte_size(), 127 Tmessage::Flush(ref flush) => flush.byte_size(), 128 Tmessage::Walk(ref walk) => walk.byte_size(), 129 Tmessage::Read(ref read) => read.byte_size(), 130 Tmessage::Write(ref write) => write.byte_size(), 131 Tmessage::Clunk(ref clunk) => clunk.byte_size(), 132 Tmessage::Remove(ref remove) => remove.byte_size(), 133 Tmessage::Attach(ref attach) => attach.byte_size(), 134 Tmessage::Auth(ref auth) => auth.byte_size(), 135 Tmessage::Statfs(ref statfs) => statfs.byte_size(), 136 Tmessage::Lopen(ref lopen) => lopen.byte_size(), 137 Tmessage::Lcreate(ref lcreate) => lcreate.byte_size(), 138 Tmessage::Symlink(ref symlink) => symlink.byte_size(), 139 Tmessage::Mknod(ref mknod) => mknod.byte_size(), 140 Tmessage::Rename(ref rename) => rename.byte_size(), 141 Tmessage::Readlink(ref readlink) => readlink.byte_size(), 142 Tmessage::GetAttr(ref getattr) => getattr.byte_size(), 143 Tmessage::SetAttr(ref setattr) => setattr.byte_size(), 144 Tmessage::XattrWalk(ref xattrwalk) => xattrwalk.byte_size(), 145 Tmessage::XattrCreate(ref xattrcreate) => xattrcreate.byte_size(), 146 Tmessage::Readdir(ref readdir) => readdir.byte_size(), 147 Tmessage::Fsync(ref fsync) => fsync.byte_size(), 148 Tmessage::Lock(ref lock) => lock.byte_size(), 149 Tmessage::GetLock(ref getlock) => getlock.byte_size(), 150 Tmessage::Link(ref link) => link.byte_size(), 151 Tmessage::Mkdir(ref mkdir) => mkdir.byte_size(), 152 Tmessage::RenameAt(ref renameat) => renameat.byte_size(), 153 Tmessage::UnlinkAt(ref unlinkat) => unlinkat.byte_size(), 154 }; 155 156 // size + type + tag + message size 157 (mem::size_of::<u32>() + mem::size_of::<u8>() + mem::size_of::<u16>()) as u32 + msg_size 158 } 159 encode<W: Write>(&self, writer: &mut W) -> io::Result<()>160 fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> { 161 self.byte_size().encode(writer)?; 162 163 let ty = match self.msg { 164 Tmessage::Version(_) => TVERSION, 165 Tmessage::Flush(_) => TFLUSH, 166 Tmessage::Walk(_) => TWALK, 167 Tmessage::Read(_) => TREAD, 168 Tmessage::Write(_) => TWRITE, 169 Tmessage::Clunk(_) => TCLUNK, 170 Tmessage::Remove(_) => TREMOVE, 171 Tmessage::Attach(_) => TATTACH, 172 Tmessage::Auth(_) => TAUTH, 173 Tmessage::Statfs(_) => TSTATFS, 174 Tmessage::Lopen(_) => TLOPEN, 175 Tmessage::Lcreate(_) => TLCREATE, 176 Tmessage::Symlink(_) => TSYMLINK, 177 Tmessage::Mknod(_) => TMKNOD, 178 Tmessage::Rename(_) => TRENAME, 179 Tmessage::Readlink(_) => TREADLINK, 180 Tmessage::GetAttr(_) => TGETATTR, 181 Tmessage::SetAttr(_) => TSETATTR, 182 Tmessage::XattrWalk(_) => TXATTRWALK, 183 Tmessage::XattrCreate(_) => TXATTRCREATE, 184 Tmessage::Readdir(_) => TREADDIR, 185 Tmessage::Fsync(_) => TFSYNC, 186 Tmessage::Lock(_) => TLOCK, 187 Tmessage::GetLock(_) => TGETLOCK, 188 Tmessage::Link(_) => TLINK, 189 Tmessage::Mkdir(_) => TMKDIR, 190 Tmessage::RenameAt(_) => TRENAMEAT, 191 Tmessage::UnlinkAt(_) => TUNLINKAT, 192 }; 193 194 ty.encode(writer)?; 195 self.tag.encode(writer)?; 196 197 match self.msg { 198 Tmessage::Version(ref version) => version.encode(writer), 199 Tmessage::Flush(ref flush) => flush.encode(writer), 200 Tmessage::Walk(ref walk) => walk.encode(writer), 201 Tmessage::Read(ref read) => read.encode(writer), 202 Tmessage::Write(ref write) => write.encode(writer), 203 Tmessage::Clunk(ref clunk) => clunk.encode(writer), 204 Tmessage::Remove(ref remove) => remove.encode(writer), 205 Tmessage::Attach(ref attach) => attach.encode(writer), 206 Tmessage::Auth(ref auth) => auth.encode(writer), 207 Tmessage::Statfs(ref statfs) => statfs.encode(writer), 208 Tmessage::Lopen(ref lopen) => lopen.encode(writer), 209 Tmessage::Lcreate(ref lcreate) => lcreate.encode(writer), 210 Tmessage::Symlink(ref symlink) => symlink.encode(writer), 211 Tmessage::Mknod(ref mknod) => mknod.encode(writer), 212 Tmessage::Rename(ref rename) => rename.encode(writer), 213 Tmessage::Readlink(ref readlink) => readlink.encode(writer), 214 Tmessage::GetAttr(ref getattr) => getattr.encode(writer), 215 Tmessage::SetAttr(ref setattr) => setattr.encode(writer), 216 Tmessage::XattrWalk(ref xattrwalk) => xattrwalk.encode(writer), 217 Tmessage::XattrCreate(ref xattrcreate) => xattrcreate.encode(writer), 218 Tmessage::Readdir(ref readdir) => readdir.encode(writer), 219 Tmessage::Fsync(ref fsync) => fsync.encode(writer), 220 Tmessage::Lock(ref lock) => lock.encode(writer), 221 Tmessage::GetLock(ref getlock) => getlock.encode(writer), 222 Tmessage::Link(ref link) => link.encode(writer), 223 Tmessage::Mkdir(ref mkdir) => mkdir.encode(writer), 224 Tmessage::RenameAt(ref renameat) => renameat.encode(writer), 225 Tmessage::UnlinkAt(ref unlinkat) => unlinkat.encode(writer), 226 } 227 } 228 decode<R: Read>(reader: &mut R) -> io::Result<Self>229 fn decode<R: Read>(reader: &mut R) -> io::Result<Self> { 230 let byte_size: u32 = WireFormat::decode(reader)?; 231 232 // byte_size includes the size of byte_size so remove that from the 233 // expected length of the message. Also make sure that byte_size is at least 234 // that long to begin with. 235 if byte_size < mem::size_of::<u32>() as u32 { 236 return Err(io::Error::new( 237 ErrorKind::InvalidData, 238 format!("byte_size(= {}) is less than 4 bytes", byte_size), 239 )); 240 } 241 242 let reader = &mut reader.take((byte_size - mem::size_of::<u32>() as u32) as u64); 243 244 let mut ty = [0u8]; 245 reader.read_exact(&mut ty)?; 246 247 let tag: u16 = WireFormat::decode(reader)?; 248 249 let msg = match ty[0] { 250 TVERSION => Ok(Tmessage::Version(WireFormat::decode(reader)?)), 251 TFLUSH => Ok(Tmessage::Flush(WireFormat::decode(reader)?)), 252 TWALK => Ok(Tmessage::Walk(WireFormat::decode(reader)?)), 253 TREAD => Ok(Tmessage::Read(WireFormat::decode(reader)?)), 254 TWRITE => Ok(Tmessage::Write(WireFormat::decode(reader)?)), 255 TCLUNK => Ok(Tmessage::Clunk(WireFormat::decode(reader)?)), 256 TREMOVE => Ok(Tmessage::Remove(WireFormat::decode(reader)?)), 257 TATTACH => Ok(Tmessage::Attach(WireFormat::decode(reader)?)), 258 TAUTH => Ok(Tmessage::Auth(WireFormat::decode(reader)?)), 259 TSTATFS => Ok(Tmessage::Statfs(WireFormat::decode(reader)?)), 260 TLOPEN => Ok(Tmessage::Lopen(WireFormat::decode(reader)?)), 261 TLCREATE => Ok(Tmessage::Lcreate(WireFormat::decode(reader)?)), 262 TSYMLINK => Ok(Tmessage::Symlink(WireFormat::decode(reader)?)), 263 TMKNOD => Ok(Tmessage::Mknod(WireFormat::decode(reader)?)), 264 TRENAME => Ok(Tmessage::Rename(WireFormat::decode(reader)?)), 265 TREADLINK => Ok(Tmessage::Readlink(WireFormat::decode(reader)?)), 266 TGETATTR => Ok(Tmessage::GetAttr(WireFormat::decode(reader)?)), 267 TSETATTR => Ok(Tmessage::SetAttr(WireFormat::decode(reader)?)), 268 TXATTRWALK => Ok(Tmessage::XattrWalk(WireFormat::decode(reader)?)), 269 TXATTRCREATE => Ok(Tmessage::XattrCreate(WireFormat::decode(reader)?)), 270 TREADDIR => Ok(Tmessage::Readdir(WireFormat::decode(reader)?)), 271 TFSYNC => Ok(Tmessage::Fsync(WireFormat::decode(reader)?)), 272 TLOCK => Ok(Tmessage::Lock(WireFormat::decode(reader)?)), 273 TGETLOCK => Ok(Tmessage::GetLock(WireFormat::decode(reader)?)), 274 TLINK => Ok(Tmessage::Link(WireFormat::decode(reader)?)), 275 TMKDIR => Ok(Tmessage::Mkdir(WireFormat::decode(reader)?)), 276 TRENAMEAT => Ok(Tmessage::RenameAt(WireFormat::decode(reader)?)), 277 TUNLINKAT => Ok(Tmessage::UnlinkAt(WireFormat::decode(reader)?)), 278 err => Err(io::Error::new( 279 ErrorKind::InvalidData, 280 format!("unknown message type {}", err), 281 )), 282 }?; 283 284 Ok(Tframe { tag, msg }) 285 } 286 } 287 288 #[derive(Debug, P9WireFormat)] 289 pub struct Tversion { 290 pub msize: u32, 291 pub version: String, 292 } 293 294 #[derive(Debug, P9WireFormat)] 295 pub struct Tflush { 296 pub oldtag: u16, 297 } 298 299 #[derive(Debug, P9WireFormat)] 300 pub struct Twalk { 301 pub fid: u32, 302 pub newfid: u32, 303 pub wnames: Vec<String>, 304 } 305 306 #[derive(Debug, P9WireFormat)] 307 pub struct Tread { 308 pub fid: u32, 309 pub offset: u64, 310 pub count: u32, 311 } 312 313 #[derive(Debug, P9WireFormat)] 314 pub struct Twrite { 315 pub fid: u32, 316 pub offset: u64, 317 pub data: Data, 318 } 319 320 #[derive(Debug, P9WireFormat)] 321 pub struct Tclunk { 322 pub fid: u32, 323 } 324 325 #[derive(Debug, P9WireFormat)] 326 pub struct Tremove { 327 pub fid: u32, 328 } 329 330 #[derive(Debug, P9WireFormat)] 331 pub struct Tauth { 332 pub afid: u32, 333 pub uname: String, 334 pub aname: String, 335 pub n_uname: u32, 336 } 337 338 #[derive(Debug, P9WireFormat)] 339 pub struct Tattach { 340 pub fid: u32, 341 pub afid: u32, 342 pub uname: String, 343 pub aname: String, 344 pub n_uname: u32, 345 } 346 347 #[derive(Debug, P9WireFormat)] 348 pub struct Tstatfs { 349 pub fid: u32, 350 } 351 352 #[derive(Debug, P9WireFormat)] 353 pub struct Tlopen { 354 pub fid: u32, 355 pub flags: u32, 356 } 357 358 #[derive(Debug, P9WireFormat)] 359 pub struct Tlcreate { 360 pub fid: u32, 361 pub name: String, 362 pub flags: u32, 363 pub mode: u32, 364 pub gid: u32, 365 } 366 367 #[derive(Debug, P9WireFormat)] 368 pub struct Tsymlink { 369 pub fid: u32, 370 pub name: String, 371 pub symtgt: String, 372 pub gid: u32, 373 } 374 375 #[derive(Debug, P9WireFormat)] 376 pub struct Tmknod { 377 pub dfid: u32, 378 pub name: String, 379 pub mode: u32, 380 pub major: u32, 381 pub minor: u32, 382 pub gid: u32, 383 } 384 385 #[derive(Debug, P9WireFormat)] 386 pub struct Trename { 387 pub fid: u32, 388 pub dfid: u32, 389 pub name: String, 390 } 391 392 #[derive(Debug, P9WireFormat)] 393 pub struct Treadlink { 394 pub fid: u32, 395 } 396 397 #[derive(Debug, P9WireFormat)] 398 pub struct Tgetattr { 399 pub fid: u32, 400 pub request_mask: u64, 401 } 402 403 #[derive(Debug, P9WireFormat)] 404 pub struct Tsetattr { 405 pub fid: u32, 406 pub valid: u32, 407 pub mode: u32, 408 pub uid: u32, 409 pub gid: u32, 410 pub size: u64, 411 pub atime_sec: u64, 412 pub atime_nsec: u64, 413 pub mtime_sec: u64, 414 pub mtime_nsec: u64, 415 } 416 417 #[derive(Debug, P9WireFormat)] 418 pub struct Txattrwalk { 419 pub fid: u32, 420 pub newfid: u32, 421 pub name: String, 422 } 423 424 #[derive(Debug, P9WireFormat)] 425 pub struct Txattrcreate { 426 pub fid: u32, 427 pub name: String, 428 pub attr_size: u64, 429 pub flags: u32, 430 } 431 432 #[derive(Debug, P9WireFormat)] 433 pub struct Treaddir { 434 pub fid: u32, 435 pub offset: u64, 436 pub count: u32, 437 } 438 439 #[derive(Debug, P9WireFormat)] 440 pub struct Tfsync { 441 pub fid: u32, 442 pub datasync: u32, 443 } 444 445 #[derive(Debug, P9WireFormat)] 446 pub struct Tlock { 447 pub fid: u32, 448 pub type_: u8, 449 pub flags: u32, 450 pub start: u64, 451 pub length: u64, 452 pub proc_id: u32, 453 pub client_id: String, 454 } 455 456 #[derive(Debug, P9WireFormat)] 457 pub struct Tgetlock { 458 pub fid: u32, 459 pub type_: u8, 460 pub start: u64, 461 pub length: u64, 462 pub proc_id: u32, 463 pub client_id: String, 464 } 465 466 #[derive(Debug, P9WireFormat)] 467 pub struct Tlink { 468 pub dfid: u32, 469 pub fid: u32, 470 pub name: String, 471 } 472 473 #[derive(Debug, P9WireFormat)] 474 pub struct Tmkdir { 475 pub dfid: u32, 476 pub name: String, 477 pub mode: u32, 478 pub gid: u32, 479 } 480 481 #[derive(Debug, P9WireFormat)] 482 pub struct Trenameat { 483 pub olddirfid: u32, 484 pub oldname: String, 485 pub newdirfid: u32, 486 pub newname: String, 487 } 488 489 #[derive(Debug, P9WireFormat)] 490 pub struct Tunlinkat { 491 pub dirfd: u32, 492 pub name: String, 493 pub flags: u32, 494 } 495 496 /// A message sent from a 9P server to a 9P client in response to a request from 497 /// that client. Encapsulates a full frame. 498 #[derive(Debug)] 499 pub enum Rmessage { 500 Version(Rversion), 501 Flush, 502 Walk(Rwalk), 503 Read(Rread), 504 Write(Rwrite), 505 Clunk, 506 Remove, 507 Attach(Rattach), 508 Auth(Rauth), 509 Statfs(Rstatfs), 510 Lopen(Rlopen), 511 Lcreate(Rlcreate), 512 Symlink(Rsymlink), 513 Mknod(Rmknod), 514 Rename, 515 Readlink(Rreadlink), 516 GetAttr(Rgetattr), 517 SetAttr, 518 XattrWalk(Rxattrwalk), 519 XattrCreate, 520 Readdir(Rreaddir), 521 Fsync, 522 Lock(Rlock), 523 GetLock(Rgetlock), 524 Link, 525 Mkdir(Rmkdir), 526 RenameAt, 527 UnlinkAt, 528 Lerror(Rlerror), 529 } 530 531 #[derive(Debug)] 532 pub struct Rframe { 533 pub tag: u16, 534 pub msg: Rmessage, 535 } 536 537 impl WireFormat for Rframe { byte_size(&self) -> u32538 fn byte_size(&self) -> u32 { 539 let msg_size = match self.msg { 540 Rmessage::Version(ref version) => version.byte_size(), 541 Rmessage::Flush => 0, 542 Rmessage::Walk(ref walk) => walk.byte_size(), 543 Rmessage::Read(ref read) => read.byte_size(), 544 Rmessage::Write(ref write) => write.byte_size(), 545 Rmessage::Clunk => 0, 546 Rmessage::Remove => 0, 547 Rmessage::Attach(ref attach) => attach.byte_size(), 548 Rmessage::Auth(ref auth) => auth.byte_size(), 549 Rmessage::Statfs(ref statfs) => statfs.byte_size(), 550 Rmessage::Lopen(ref lopen) => lopen.byte_size(), 551 Rmessage::Lcreate(ref lcreate) => lcreate.byte_size(), 552 Rmessage::Symlink(ref symlink) => symlink.byte_size(), 553 Rmessage::Mknod(ref mknod) => mknod.byte_size(), 554 Rmessage::Rename => 0, 555 Rmessage::Readlink(ref readlink) => readlink.byte_size(), 556 Rmessage::GetAttr(ref getattr) => getattr.byte_size(), 557 Rmessage::SetAttr => 0, 558 Rmessage::XattrWalk(ref xattrwalk) => xattrwalk.byte_size(), 559 Rmessage::XattrCreate => 0, 560 Rmessage::Readdir(ref readdir) => readdir.byte_size(), 561 Rmessage::Fsync => 0, 562 Rmessage::Lock(ref lock) => lock.byte_size(), 563 Rmessage::GetLock(ref getlock) => getlock.byte_size(), 564 Rmessage::Link => 0, 565 Rmessage::Mkdir(ref mkdir) => mkdir.byte_size(), 566 Rmessage::RenameAt => 0, 567 Rmessage::UnlinkAt => 0, 568 Rmessage::Lerror(ref lerror) => lerror.byte_size(), 569 }; 570 571 // size + type + tag + message size 572 (mem::size_of::<u32>() + mem::size_of::<u8>() + mem::size_of::<u16>()) as u32 + msg_size 573 } 574 encode<W: Write>(&self, writer: &mut W) -> io::Result<()>575 fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> { 576 self.byte_size().encode(writer)?; 577 578 let ty = match self.msg { 579 Rmessage::Version(_) => RVERSION, 580 Rmessage::Flush => RFLUSH, 581 Rmessage::Walk(_) => RWALK, 582 Rmessage::Read(_) => RREAD, 583 Rmessage::Write(_) => RWRITE, 584 Rmessage::Clunk => RCLUNK, 585 Rmessage::Remove => RREMOVE, 586 Rmessage::Attach(_) => RATTACH, 587 Rmessage::Auth(_) => RAUTH, 588 Rmessage::Statfs(_) => RSTATFS, 589 Rmessage::Lopen(_) => RLOPEN, 590 Rmessage::Lcreate(_) => RLCREATE, 591 Rmessage::Symlink(_) => RSYMLINK, 592 Rmessage::Mknod(_) => RMKNOD, 593 Rmessage::Rename => RRENAME, 594 Rmessage::Readlink(_) => RREADLINK, 595 Rmessage::GetAttr(_) => RGETATTR, 596 Rmessage::SetAttr => RSETATTR, 597 Rmessage::XattrWalk(_) => RXATTRWALK, 598 Rmessage::XattrCreate => RXATTRCREATE, 599 Rmessage::Readdir(_) => RREADDIR, 600 Rmessage::Fsync => RFSYNC, 601 Rmessage::Lock(_) => RLOCK, 602 Rmessage::GetLock(_) => RGETLOCK, 603 Rmessage::Link => RLINK, 604 Rmessage::Mkdir(_) => RMKDIR, 605 Rmessage::RenameAt => RRENAMEAT, 606 Rmessage::UnlinkAt => RUNLINKAT, 607 Rmessage::Lerror(_) => RLERROR, 608 }; 609 610 ty.encode(writer)?; 611 self.tag.encode(writer)?; 612 613 match self.msg { 614 Rmessage::Version(ref version) => version.encode(writer), 615 Rmessage::Flush => Ok(()), 616 Rmessage::Walk(ref walk) => walk.encode(writer), 617 Rmessage::Read(ref read) => read.encode(writer), 618 Rmessage::Write(ref write) => write.encode(writer), 619 Rmessage::Clunk => Ok(()), 620 Rmessage::Remove => Ok(()), 621 Rmessage::Attach(ref attach) => attach.encode(writer), 622 Rmessage::Auth(ref auth) => auth.encode(writer), 623 Rmessage::Statfs(ref statfs) => statfs.encode(writer), 624 Rmessage::Lopen(ref lopen) => lopen.encode(writer), 625 Rmessage::Lcreate(ref lcreate) => lcreate.encode(writer), 626 Rmessage::Symlink(ref symlink) => symlink.encode(writer), 627 Rmessage::Mknod(ref mknod) => mknod.encode(writer), 628 Rmessage::Rename => Ok(()), 629 Rmessage::Readlink(ref readlink) => readlink.encode(writer), 630 Rmessage::GetAttr(ref getattr) => getattr.encode(writer), 631 Rmessage::SetAttr => Ok(()), 632 Rmessage::XattrWalk(ref xattrwalk) => xattrwalk.encode(writer), 633 Rmessage::XattrCreate => Ok(()), 634 Rmessage::Readdir(ref readdir) => readdir.encode(writer), 635 Rmessage::Fsync => Ok(()), 636 Rmessage::Lock(ref lock) => lock.encode(writer), 637 Rmessage::GetLock(ref getlock) => getlock.encode(writer), 638 Rmessage::Link => Ok(()), 639 Rmessage::Mkdir(ref mkdir) => mkdir.encode(writer), 640 Rmessage::RenameAt => Ok(()), 641 Rmessage::UnlinkAt => Ok(()), 642 Rmessage::Lerror(ref lerror) => lerror.encode(writer), 643 } 644 } 645 decode<R: Read>(reader: &mut R) -> io::Result<Self>646 fn decode<R: Read>(reader: &mut R) -> io::Result<Self> { 647 let byte_size: u32 = WireFormat::decode(reader)?; 648 649 // byte_size includes the size of byte_size so remove that from the 650 // expected length of the message. 651 let reader = &mut reader.take((byte_size - mem::size_of::<u32>() as u32) as u64); 652 653 let mut ty = [0u8]; 654 reader.read_exact(&mut ty)?; 655 656 let tag: u16 = WireFormat::decode(reader)?; 657 658 let msg = match ty[0] { 659 RVERSION => Ok(Rmessage::Version(WireFormat::decode(reader)?)), 660 RFLUSH => Ok(Rmessage::Flush), 661 RWALK => Ok(Rmessage::Walk(WireFormat::decode(reader)?)), 662 RREAD => Ok(Rmessage::Read(WireFormat::decode(reader)?)), 663 RWRITE => Ok(Rmessage::Write(WireFormat::decode(reader)?)), 664 RCLUNK => Ok(Rmessage::Clunk), 665 RREMOVE => Ok(Rmessage::Remove), 666 RATTACH => Ok(Rmessage::Attach(WireFormat::decode(reader)?)), 667 RAUTH => Ok(Rmessage::Auth(WireFormat::decode(reader)?)), 668 RSTATFS => Ok(Rmessage::Statfs(WireFormat::decode(reader)?)), 669 RLOPEN => Ok(Rmessage::Lopen(WireFormat::decode(reader)?)), 670 RLCREATE => Ok(Rmessage::Lcreate(WireFormat::decode(reader)?)), 671 RSYMLINK => Ok(Rmessage::Symlink(WireFormat::decode(reader)?)), 672 RMKNOD => Ok(Rmessage::Mknod(WireFormat::decode(reader)?)), 673 RRENAME => Ok(Rmessage::Rename), 674 RREADLINK => Ok(Rmessage::Readlink(WireFormat::decode(reader)?)), 675 RGETATTR => Ok(Rmessage::GetAttr(WireFormat::decode(reader)?)), 676 RSETATTR => Ok(Rmessage::SetAttr), 677 RXATTRWALK => Ok(Rmessage::XattrWalk(WireFormat::decode(reader)?)), 678 RXATTRCREATE => Ok(Rmessage::XattrCreate), 679 RREADDIR => Ok(Rmessage::Readdir(WireFormat::decode(reader)?)), 680 RFSYNC => Ok(Rmessage::Fsync), 681 RLOCK => Ok(Rmessage::Lock(WireFormat::decode(reader)?)), 682 RGETLOCK => Ok(Rmessage::GetLock(WireFormat::decode(reader)?)), 683 RLINK => Ok(Rmessage::Link), 684 RMKDIR => Ok(Rmessage::Mkdir(WireFormat::decode(reader)?)), 685 RRENAMEAT => Ok(Rmessage::RenameAt), 686 RUNLINKAT => Ok(Rmessage::UnlinkAt), 687 RLERROR => Ok(Rmessage::Lerror(WireFormat::decode(reader)?)), 688 err => Err(io::Error::new( 689 ErrorKind::InvalidData, 690 format!("unknown message type {}", err), 691 )), 692 }?; 693 694 Ok(Rframe { tag, msg }) 695 } 696 } 697 698 #[derive(Debug, Copy, Clone, P9WireFormat)] 699 pub struct Qid { 700 pub ty: u8, 701 pub version: u32, 702 pub path: u64, 703 } 704 705 #[derive(Debug, P9WireFormat)] 706 pub struct Dirent { 707 pub qid: Qid, 708 pub offset: u64, 709 pub ty: u8, 710 pub name: String, 711 } 712 713 #[derive(Debug, P9WireFormat)] 714 pub struct Rversion { 715 pub msize: u32, 716 pub version: String, 717 } 718 719 #[derive(Debug, P9WireFormat)] 720 pub struct Rwalk { 721 pub wqids: Vec<Qid>, 722 } 723 724 #[derive(Debug, P9WireFormat)] 725 pub struct Rread { 726 pub data: Data, 727 } 728 729 #[derive(Debug, P9WireFormat)] 730 pub struct Rwrite { 731 pub count: u32, 732 } 733 734 #[derive(Debug, P9WireFormat)] 735 pub struct Rauth { 736 pub aqid: Qid, 737 } 738 739 #[derive(Debug, P9WireFormat)] 740 pub struct Rattach { 741 pub qid: Qid, 742 } 743 744 #[derive(Debug, P9WireFormat)] 745 pub struct Rlerror { 746 pub ecode: u32, 747 } 748 749 #[derive(Debug, P9WireFormat)] 750 pub struct Rstatfs { 751 pub ty: u32, 752 pub bsize: u32, 753 pub blocks: u64, 754 pub bfree: u64, 755 pub bavail: u64, 756 pub files: u64, 757 pub ffree: u64, 758 pub fsid: u64, 759 pub namelen: u32, 760 } 761 762 #[derive(Debug, P9WireFormat)] 763 pub struct Rlopen { 764 pub qid: Qid, 765 pub iounit: u32, 766 } 767 768 #[derive(Debug, P9WireFormat)] 769 pub struct Rlcreate { 770 pub qid: Qid, 771 pub iounit: u32, 772 } 773 774 #[derive(Debug, P9WireFormat)] 775 pub struct Rsymlink { 776 pub qid: Qid, 777 } 778 779 #[derive(Debug, P9WireFormat)] 780 pub struct Rmknod { 781 pub qid: Qid, 782 } 783 784 #[derive(Debug, P9WireFormat)] 785 pub struct Rreadlink { 786 pub target: String, 787 } 788 789 #[derive(Debug, P9WireFormat)] 790 pub struct Rgetattr { 791 pub valid: u64, 792 pub qid: Qid, 793 pub mode: u32, 794 pub uid: u32, 795 pub gid: u32, 796 pub nlink: u64, 797 pub rdev: u64, 798 pub size: u64, 799 pub blksize: u64, 800 pub blocks: u64, 801 pub atime_sec: u64, 802 pub atime_nsec: u64, 803 pub mtime_sec: u64, 804 pub mtime_nsec: u64, 805 pub ctime_sec: u64, 806 pub ctime_nsec: u64, 807 pub btime_sec: u64, 808 pub btime_nsec: u64, 809 pub gen: u64, 810 pub data_version: u64, 811 } 812 813 #[derive(Debug, P9WireFormat)] 814 pub struct Rxattrwalk { 815 pub size: u64, 816 } 817 818 #[derive(Debug, P9WireFormat)] 819 pub struct Rreaddir { 820 pub data: Data, 821 } 822 823 #[derive(Debug, P9WireFormat)] 824 pub struct Rlock { 825 pub status: u8, 826 } 827 828 #[derive(Debug, P9WireFormat)] 829 pub struct Rgetlock { 830 pub ty: u8, 831 pub start: u64, 832 pub length: u64, 833 pub proc_id: u32, 834 pub client_id: String, 835 } 836 837 #[derive(Debug, P9WireFormat)] 838 pub struct Rmkdir { 839 pub qid: Qid, 840 } 841