• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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