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