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